Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens to exceptions raised in a with statement expression?

My understanding of Python's with statement is as follows:

with statement = with + expression + as + target + : + suit

  1. expression is executed and returns a context manager
  2. context manager's __enter__ returns a value to target
  3. The suite is executed.
  4. context manager's __exit__ method is invoked

I know exceptions can be handled in step2 and step3, my question is that if an exception is thrown during the step1 when expression is executed, can I get a context manager?

If not does that mean that the with statement just ensures the suit to be executed and close properly?

Like with open("file") as f, if the file does not exist what will happen?

like image 367
vergil Avatar asked Jun 18 '15 07:06

vergil


People also ask

What happens when an exception is raised?

When an exception is raised, no further statements in the current block of code are executed.

What happens when an exception is raised in a program in Python?

Python Exceptions. When a Python program meets an error, it stops the execution of the rest of the program. An error in Python might be either an error in the syntax of an expression or a Python exception.

Does raise stop the program?

The effect of a raise statement is to either divert execution in a matching except suite, or to stop the program because no matching except suite was found to handle the exception. The exception object created by raise can contain a message string that provides a meaningful error message.

Will be executed if the try block raises an error?

Since the try block raises an error, the except block will be executed.


1 Answers

The with statement only manages exceptions in step 3. If an exception is raised in step 1 (executing expression) or in step 2 (executing the context manager __enter__ method), you do not have a (valid and working) context manager to hand the exception to.

So if the file does not exist, an exception is raised in step 1 and cannot be handled by a context manager, because that context manager was never created.

If that is a problem, you can always execute the expression part separately:

try:
    context_manager = expression
except SomeSpecificException:
    # do something about the exception
else:
    with context_manager as target:
        # execute the suite

If the exception is raised in __enter__ (step 2) the context hasn’t yet been entered and so __exit__ will not be called. Your only option to handle an exception at that step is to put the whole with statement inside a try...except block.

like image 145
Martijn Pieters Avatar answered Sep 17 '22 13:09

Martijn Pieters