Simplicity Simplicity - 28 days ago 14
Python Question

Error with context manager definition

I have the following Python script:

from contextlib import contextmanager

@contextmanager
def my_content_manager():
self.entrance = True

try:
yield
except Exception as ex:
self.entrance = False

with my_content_manager() as cm:
print (cm.entrance)

print (cm.entrance)


When I tried to run the script, I got the following:

Traceback (most recent call last):
File "test.py", line 12, in <module>
with my_content_manager() as cm:
File "C:\Users\abc\AppData\Local\Programs\Python\Python36\lib\contextlib.py", line 82, in __enter__
return next(self.gen)
File "test.py", line 5, in my_content_manager
self.entrance = True
NameError: name 'self' is not defined


Why is that? How can I solve this error?

Thanks.

Answer

In general, using a class is probably a better way to go (as the other answer suggests). However, I remembered that function objects can have attributes. I came across this related question, which lead to the following trick (which does seem like an abuse of the feature):

from contextlib import contextmanager

@contextmanager
def my_content_manager():
    my_content_manager.entrance = True
    try:
        yield my_content_manager.entrance
    finally:
        my_content_manager.entrance = False
my_content_manager.entrance = False

with my_content_manager() as cm:
    print(my_content_manager.entrance)
    # Or, print(cm)

print(my_content_manager.entrance)

There are probably pitfalls to this technique. I'm simply posting it as a curiosity.