Why can't a module be a context manager (with a 'with' expression)?

Suppose we have the following mod.py:

def __enter__():
    print("__enter__<")

def __exit__(*exc):
    print("__exit__< {0}".format(exc))

class cls:
    def __enter__(self):
        print("cls.__enter__<")

    def __exit__(self, *exc):
        print("cls.__exit__< {0}".format(exc))

and its subsequent use:

import mod

with mod:
    pass

I get an error message:

Traceback (most recent call last):
  File "./test.py", line 3, in <module>
    with mod:
AttributeError: __exit__

According to the documentation, the documentation withshould be executed as follows (I believe that it does not work in step 2 and therefore truncates the list):

  • The context expression (the expression specified in the with_item parameter) is evaluated to obtain the context manager.
  • Context Managers __exit__()are loaded for later use.
  • The context manager method is called __enter__().
  • etc...

, , __exit__ . -, , ?

+4
2

__exit__ - , Python . module , .

. Datamodel:

, , , .

, . , __str__ __repr__ , .

Python , , ; Python , , __hash__ ( , self).

+7

, @Martijn Pieters answer. , sys.modules , , .

, . mod.py:

import sys

class MyModule(object):
    def __enter__(self):
        print("__enter__<")

    def __exit__(self, *exc):
        print("__exit__> {0}".format(exc))

# replace entry in sys.modules for this module with an instance of MyModule
_ref = sys.modules[__name__]
sys.modules[__name__] = MyModule()

:

import mod

with mod:
    print('running within context')

:

__enter__<
running within context
__exit__> (None, None, None)

. , _ref.

+2

Source: https://habr.com/ru/post/1660763/


All Articles