Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to hundreds of tutorials and a community of expert Pythonistas.

Unlock This Lesson

How Context Managers Work, Step by Step

Give Feedback

Comments & Discussion

blu on June 13, 2019

What happens when nesting with statements for the same object? Let’s say I have an instance foo of class Bar, which has a context manager defined

class Bar:

    def __init__(self):
        my_resource = None

    def __enter__(self):
        my_resource = allocate_resource()

    def __exit__(self, ...):
        free_resource(my_resource)

what happens if I nest WITH statements like this:

foo = Bar()

with foo:
    with foo:
        with foo:
            do_something

Does Python handle that for me? I.e. will it only call enter upon the first WITH statement and exit when exiting from the same level?

If not, how should I handle this myself? If I have enter check whetehr the resource is already allocated and only allocate it, if not, it will be released upon exiting the innermost level, so that’s not an option, I believe. Alternatively, I could use a nesting counter:

def __init__(self):
    self.my_resource = None
    self.counter = 0

def __enter__(self):
    if self.counter == 0:
        self.my_resource = allocate_resource()
    self.counter += 1

def __exit__(self, ...):
    if self.counter == 1: 
        free_resource(self.my_resource)
    self.counter -= 1

How will that work if an exception occurs? Will exit be called the necessary number of times, so that the resource is eventually freed up?

Become a Member to join the conversation.