Error handling in context managers

Peter Otten __peter__ at web.de
Tue Jan 17 03:34:13 EST 2017


Gregory Ewing wrote:

> Israel Brewster wrote:
>> The problem is that, from time to time, I can't get a connection, the
>> result being that cursor is None,
> 
> That's your problem right there -- you want a better-behaved
> version of psql_cursor().
> 
> def get_psql_cursor():
>     c = psql_cursor()
>     if c is None:
>        raise CantGetAConnectionError()
>     return c
> 
> with get_psql_cursor() as c:
>     ...

You still need to catch the error -- which leads to option (3) in my zoo, 
the only one that is actually usable. If one contextmanager cannot achieve 
what you want, use two:
 
$ cat conditional_context_raise.py
import sys
from contextlib import contextmanager

class NoConnection(Exception):
    pass

class Cursor:
    def execute(self, sql):
        print("EXECUTING", sql)

@contextmanager
def cursor():
    if "--fail" in sys.argv:
        raise NoConnection
    yield Cursor()

@contextmanager
def no_connection():
    try:
        yield
    except NoConnection:
        print("no connection")

with no_connection(), cursor() as cs:
    cs.execute("insert into...")
$ python3 conditional_context_raise.py
EXECUTING insert into...
$ python3 conditional_context_raise.py --fail
no connection

If you want to ignore the no-connection case use 
contextlib.suppress(NoConnection) instead of the custom no_connection() 
manager.



More information about the Python-list mailing list