Catching exception in context manager __enter__()

python context manager exception in __enter__
context manager generator doesn t implement __enter__ and __exit__
python context manager database connection
contextmanager attributeerror: __enter__
python context manager stack overflow
python context manager without with
java context manager
python ignore exception context manager

Is it possible to ensure the __exit__() method is called even if there is an exception in __enter__()?

>>> class TstContx(object):
...    def __enter__(self):
...        raise Exception('Oops in __enter__')
...
...    def __exit__(self, e_typ, e_val, trcbak):
...        print "This isn't running"
... 
>>> with TstContx():
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in __enter__
Exception: Oops in __enter__
>>> 

Edit

This is as close as I could get...

class TstContx(object):
    def __enter__(self):
        try:
            # __enter__ code
        except Exception as e
            self.init_exc = e

        return self

    def __exit__(self, e_typ, e_val, trcbak):
        if all((e_typ, e_val, trcbak)):
            raise e_typ, e_val, trcbak

        # __exit__ code


with TstContx() as tc:
    if hasattr(tc, 'init_exc'): raise tc.init_exc

    # code in context

In hind sight, a context manager might have not been the best design decision


Like this:

import sys

class Context(object):
    def __enter__(self):
        try:
            raise Exception("Oops in __enter__")
        except:
            # Swallow exception if __exit__ returns a True value
            if self.__exit__(*sys.exc_info()):
                pass
            else:
                raise


    def __exit__(self, e_typ, e_val, trcbak):
        print "Now it's running"


with Context():
    pass

To let the program continue on its merry way without executing the context block you need to inspect the context object inside the context block and only do the important stuff if __enter__ succeeded.

class Context(object):
    def __init__(self):
        self.enter_ok = True

    def __enter__(self):
        try:
            raise Exception("Oops in __enter__")
        except:
            if self.__exit__(*sys.exc_info()):
                self.enter_ok = False
            else:
                raise
        return self

    def __exit__(self, e_typ, e_val, trcbak):
        print "Now this runs twice"
        return True


with Context() as c:
    if c.enter_ok:
        print "Only runs if enter succeeded"

print "Execution continues"

As far as I can determine, you can't skip the with-block entirely. And note that this context now swallows all exceptions in it. If you wish not to swallow exceptions if __enter__ succeeds, check self.enter_ok in __exit__ and return False if it's True.

contextlib — Utilities for with-statement contexts — Python 3.8.5 , Context managers inheriting from ContextDecorator have to implement __enter __ and __exit__ as normal. __exit__ retains its optional exception handling even � The return value is the result of the context manager’s own __enter__() method. These context managers may suppress exceptions just as they normally would if used directly as part of a with statement. push (exit) ¶ Adds a context manager’s __exit__() method to the callback stack.


No. If there is the chance that an exception could occur in __enter__() then you will need to catch it yourself and call a helper function that contains the cleanup code.

A Gentle Introduction to Context Managers: The Pythonic Way of , I used tryexceptfinally blocks ( try-catch-finally in C# & JavaScript) to __exit __ is called on the original Context Manager object, not the Once the code block is entered, __exit__ is always called, even if an exception is� Python calls __enter__ when execution enters the context of the with statement and it’s time to acquire the resource. When execution leaves the context again, Python calls __exit__ to free up the resource. Writing a class-based context manager isn’t the only way to support the with statement in Python.


You could use contextlib.ExitStack (not tested):

with ExitStack() as stack:
    cm = TstContx()
    stack.push(cm) # ensure __exit__ is called
    with ctx:
         stack.pop_all() # __enter__ succeeded, don't call __exit__ callback

Or an example from the docs:

stack = ExitStack()
try:
    x = stack.enter_context(cm)
except Exception:
    # handle __enter__ exception
else:
    with stack:
        # Handle normal case

See contextlib2 on Python <3.3.

Context Managers & with statement | by Rachit Tayal, Specify the __enter__ & __exit__ context manager methods to by abstracting the try/catch exception handling inside context managers. Trying to understanding how context managers work to catch errors, but more specifically the role of the __enter__() method in a class created to be used as a context


if inheritance or complex subroutines are not required, you can use a shorter way:

from contextlib import contextmanager

@contextmanager
def test_cm():
    try:
        # dangerous code
        yield  
    except Exception, err
        pass # do something

26. Context Managers — Python Tips 0.1 documentation, At the very least a context manager has an __enter__ and __exit__ method defined. Let's make our Let's try handling the exception in the __exit__ method: . class catch_threading_exception: """ Context manager catching threading.Thread exception using: threading.excepthook. Attributes set when an exception is catched: * exc_type * exc_value * exc_traceback * thread: See threading.excepthook() documentation for these attributes. These attributes are deleted at the context manager exit. Usage:


I suggest you follow RAII (resource acquisition is initialization) and use the constructor of your context to do the potentially failing allocation. Then your __enter__ can simply return self which should never ever raise an exception. If your constructor fails, the exception may be thrown before even entering the with context.

class Foo:
    def __init__(self):
        print("init")
        raise Exception("booh")

    def __enter__(self):
        print("enter")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")
        return False


with Foo() as f:
    print("within with")

Output:

init
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  ...
    raise Exception("booh")
Exception: booh

Python context managers � GitHub, _msg = msg def __enter__(self): # time.monotonic() requires Python >= 3.3 self. Context managers can also handle exceptions from inside the block they� Here is a class which can be used as either a decorator or context manager for guarding against the given exceptions. It takes an exception (or a tuple of exceptions) as argument, and if the wrapped code raises that exception, it is re-raised as another exception type (by default RuntimeError). For example:


contextlib – Context manager utilities, python contextlib_api.py __init__() __enter__() Doing work in the context If the context manager can handle the exception, __exit__() should return a true� @@ -3040,6 +3040,18 @@ class catch_unraisable_exception: """ Context manager catching unraisable exception using sys.unraisablehook. If the *object* attribute of the unraisable hook is set and the object is: being finalized, the object is resurrected because the context manager: stores a strong reference to it (cm.unraisable.object).


contextlib — Context Manager Utilities — PyMOTW 3, The __enter__() method can return any object to be associated with a If the context manager can handle the exception, __exit__() should� 29.6.1. Utilities¶. Functions and classes provided: @contextlib.contextmanager¶ This function is a decorator that can be used to define a factory function for with statement context managers, without needing to create a class or separate __enter__() and __exit__() methods.


The Truth About Context Managers In Python, These methods of the context manager are __enter()__ and __exit()__ and are known popularly __exit__() method and Handling Exceptions. I'm often faced with the situation that depending on some command line argument, input might either come from a file or standard input. The same goes for output. I really like how context managers in python 3 work, and therefore try to make all my open calls part of some with statement.