Context managers
لم يُترجم بعد؛ يُعرض باللغة الإنجليزية
A context manager is an object that sets something up and is guaranteed to clean it up again: close the file, release the lock, turn the lights off. Step through the with statement as Python runs it: it makes the manager, calls __enter__, binds its return value with as, runs the block, and calls __exit__ even when the block fails. Then see how __exit__'s return value decides whether an error is swallowed, and write the same manager in five lines with @contextmanager.
5 أسئلة سريعة
اختر إجابة لتعرف السبب. تُحفَظ نتيجتك مع تقدّمك.
01In with Lights() as r: what ends up in r?
as binds the return value of __enter__. Often that is the manager itself (a file's __enter__ returns the file), but here __enter__ returns 'room', so r is 'room'.
02The block inside a with statement raises ZeroDivisionError. What happens next?
The with statement always calls __exit__ when the block ends, for any reason. On an error it passes three arguments (type, exception, traceback); a true return swallows the error, a false one lets it carry on.
03__exit__ returns False after an error in the block. What does the program do?
False (or None, or no return at all) means do not suppress. The clean-up in __exit__ has already run, so lights off is printed before the traceback.
04With @contextmanager, where does the clean-up belong so that it still runs when the with block fails?
An error in the with block is raised inside the generator at the yield. Code after the yield runs then only if it sits in finally (or an except that handles the error).
05Which of these is NOT a reason to use with?
with is about guaranteed clean-up: files, locks, connections, temporary settings. It does not change how fast code runs.
المسرد
- Context manager
- An object with __enter__ and __exit__ methods that sets something up before a with block and cleans it up afterwards.
- with statement
- Runs a block of code inside a context manager: calls __enter__ first and __exit__ when the block ends, for any reason.
- __enter__
- The set-up method. The with statement calls it before the block; its return value is what as binds.
- __exit__
- The clean-up method, called with three arguments: the error's type, the error and its traceback, or three Nones when the block ended normally.
- Suppress (an exception)
- Stop an error from going any further. A context manager does it by returning a true value from __exit__.
- Traceback
- The report Python prints when an error stops a program: where it happened and what the error was.
- @contextmanager
- A decorator in contextlib that turns a generator function into a context manager: code before yield is the set-up, code after it the clean-up.
الملاحظات والمصادر
- The with statement loads __enter__ and __exit__ from the manager before it calls __enter__, so an object missing either one fails with TypeError before any set-up runs.
- __exit__ always gets three arguments after self. When the block ends without an error all three are None; on an error they are the exception's type, the exception and its traceback.
- Any true value returned by __exit__ suppresses the error, and False, None or no return at all lets it carry on. The Python docs advise against re-raising the passed-in error inside __exit__: return a false value instead.
- With @contextmanager, the error from the block is raised inside the generator at the yield, which is why the clean-up belongs in try/finally. Leave out the try/finally and an error would skip it.
- The figure shortens the traceback. The real one shows the full path to lights.py, then line 11 itself with ~~^~~ marks under the division.
- Many standard objects are context managers: open() files, threading.Lock, socket connections and decimal.localcontext(), so with works with all of them.
- Python reference: The with statement
- Python reference: With statement context managers (__enter__, __exit__)
- Python library: Context manager types
- Python library: contextlib (contextmanager, suppress)
- Python tutorial: Predefined clean-up actions
- Python glossary: context manager
- Python library: Built-in exceptions (ZeroDivisionError)
- PEP 343: The "with" Statement
اختبار يتاح بعد الخطوة الأخيرة.