Search code examples
pythonwith-statementcontextmanagercode-inspection

Where is a Python built-in object's __enter__() and __exit__() defined?


I've read that the object's __ enter__() and __ exit__() methods are called every time 'with' is used. I understand that for user-defined objects, you can define those methods yourself, but I don't understand how this works for built-in objects/functions like 'open' or even the testcases.

This code works as expected and I assume it closes the file with __ exit__():

with open('output.txt', 'w') as f:
    f.write('Hi there!')

or

with self.assertRaises(ValueError):
    remove_driver(self.driver)  # self refers to a class that inherits from the default unittest.TestCase

Yet, there's no such __ enter__() or __ exit__() method on either object when I inspect it:

enter image description here

enter image description here

So how is 'open' working with 'with'? Shouldn't objects that support context management protocol have __ enter__() and __ exit__() methods defined and inspectable?


Solution

  • open() is a function. It returns something that has an __enter__ and __exit__ method. Look at something like this:

    >>> class f:
    ...     def __init__(self):
    ...         print 'init'
    ...     def __enter__(self):
    ...         print 'enter'
    ...     def __exit__(self, *a):
    ...         print 'exit'
    ... 
    >>> with f():
    ...     pass
    ... 
    init
    enter
    exit
    >>> def return_f():
    ...     return f()
    ... 
    >>> with return_f():
    ...     pass
    ... 
    init
    enter
    exit
    

    Of course, return_f itself does not have those methods, but what it returns does.