6. Context Managers

Local variables in Python have function scope, and thus the target of a with statement, if any, is still visible after the block has exited, though __exit__() has already been called on the context manager (the argument of the with statement), and thus is often not useful or valid.

  • __enter__()
  • __exit__()

6.1. Zastosowanie

  • Połączenia do bazy danych
  • Pliki
  • Stream siecowe

6.2. Przykład

f = open(filename)
# ...
f.close()
f = open(filename)
try:
    # ...
finally:
    f.close()
with open(filename) as f:
    # ...

Dzieli naszą funkcję na bloki przed i po yield.

  • Bloki przed traktuje jako __enter__()
  • Bloki za traktuje jako __exit__()
from contextlib import contextmanager

@contextmanager
def tag(name):
    print("<%s>" % name)
    yield
    print("</%s>" % name)

>>> with tag("h1"):
...    print("foo")
...
<h1>
foo
</h1>

6.3. Przykład praktyczny

Code Listing 6.1. Context Manager
class File:

    def __init__(self, name, content=[]):
        self.name = name
        self.content = content

    def append(self, line):
        self.content.extend(line)

    def write(self):
        with open(self.name, 'w') as file:
            file.write(self.content)

    def __enter__(self):
        pass

    def __exit__(self, **kwargs):
        return self.write()


with File('asd.txt') as file:
    file.append('nowa linia')

# dopiero po wyjsciu z with, plik zostanie zapisany