0

Assuming this piece of code:

connection = get_some_connection() # maybe from oursql
with connection.cursor() as cursor:
    cursor.execute('some query')

I understand that after finishing cursor.close() will be executed automatically. What about exceptions? Must I put them inside?

connection = get_some_connection() # maybe from oursql
with connection.cursor() as cursor:
    try:
        cursor.execute('some query')
    except IntegrityError, e:
        # handle exceoption

Or is there a nicer way to handle them with the with statement?

2 Answers 2

4

with x as y: z() is basically syntactic sugar for:

y = x
y.__enter__()
try:
    z()
finally:
    if y.__exit__: y.__exit__()

This is not completely accurate, but that's the gist of it. Note that __exit__() will be passed exception information if an exception was thrown (see the docs) so you can "handle" an exception this way, but this will not keep the exception from being thrown up the call stack.

If you want to handle the exception gracefully and consume it, you need to use a try/catch block. It can be inside the with block or outside of it, as long as the try block is active when the exception is raised.

Sign up to request clarification or add additional context in comments.

1 Comment

Because of how the exception propagates, could you not also put the try/catch immediately outside the with block? ;)
2

In the particular case of oursql,

with some_connection.cursor() as cursor:
    do_something_with(cursor)

is equivalent to

cursor = some_connection.cursor()
try:
    do_something_with(cursor)
except:
    some_connection.rollback()
    raise
else:
    some_connection.commit()
finally:
    cursor.close()

As you can see, what a with statement does depends on the context manager (e.g. some_connection.cursor()`).

with connection.cursor() as cursor:
    try:
        cursor.execute('some query')
    except IntegrityError as e:
        # handle exception

may or may not be the correct way to handle an IntegrityError -- you might want to handle the IntegrityError in some outer scope.

For example, if you had some generic function which logs queries such as

def log_query(query):
    logger.info(query)
    with connection.cursor() as cursor:
        cursor.execute(query)

try:
    log_query(query)
except IntegrityError as err:
     # handler error

you may not want to handle IntegrityErrors inside log_query, but rather at a later stage.

1 Comment

Note that if you do handle the error internally, and don't re-raise, then you had better handle it in a way that is compatible with the some_connection.commit() that happens when the cursor's with-block cleans up :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.