Murali K
Murali K

Reputation: 206

Is __exit__ method called when there's an exception inside context manager?

Imagine we have a context manager called abc. So in the below code does the __exit__method defined inside abc be called if there's an exception.

with abc:
    print("entered context manager")
    raise Exception("raising exception")


Upvotes: 3

Views: 7004

Answers (2)

Taras  Mykhalchuk
Taras Mykhalchuk

Reputation: 927

Let's say this is your custom context manager:

class CustomTransaction(object):

    def __init__(self, id):
        self.id = id
        print('init')

    def __enter__(self):
        if self.id:
            print('User_{} acquired transaction lock'.format(self.id))
        else:
            print('Raising an exception from __enter__ method')
            raise Exception('id was not specified')

        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            print('User_{} released transaction lock'.format(self.id))
        else:
            print('User_{} failed to complete transaction block'.format(self.id))

Here is how it's going to behave depending on if and where an exception occurs:

1. Transaction block won't be completed

with CustomTransaction(id=1) as t:
    print('Doing some work...')
    print('Raising an exception...')
    raise Exception('Error. Something went wrong!')
    print('Won\'t be printed...')

output:

init
User_1 acquired transaction lock
Doing some work...
Raising an exception...
User_1 failed to complete transaction block

2. Transaction block will be successfully completed

with CustomTransaction(id=2) as t:
    print('Doing some work...')
    print('Doing even more heavy work...')

output:

init
User_2 acquired transaction lock
Doing some work...
Doing even more heavy work...
User_2 released transaction lock

3. Transaction block won't even start excecuting because the enter method raises an exception

with CustomTransaction(None) as t:
    print('Won\'t be printed')

output:

init
Raising an exception from the __enter__ method

Upvotes: 2

Ralf
Ralf

Reputation: 16515

Yes, according to the docs. The __exit__ method receives the exception as arguments:

object.__exit__(self, exc_type, exc_value, traceback)

Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be None.

This question has a lot more answers and information.

It was the first google result when I typed in python __exit__ exception.

Upvotes: 2

Related Questions