| title |
|---|
Python / Context Manager |
Python / Context Manager
-
3. Data model — Python 2.7.15 documentation
-
New in version 2.5. A context manager is an object that defines the RUNTIME CONTEXT to be established when executing a
withstatement.The context manager handles the entry into, and the exit from, the desired runtime context for the execution of the block of code.
-
Context managers are normally invoked using the
withstatement (described in section Thewithstatement), but can also be used by DIRECTLY INVOKING their methods.呼叫
__enter__()不會很怪嗎 ?? -
Typical uses of context managers include saving and restoring various kinds of global state, locking and unlocking resources, closing opened files, etc.
其中 "global state" 的用法,很像是 mock 裡
with patch()的用法。
object.__enter__(self)-
Enter the runtime context RELATED TO THIS OBJECT. The
withstatement will BIND this method’s return value to the TARGET(S) specified in theasclause of the statement, if any.注意 "target(s)" 的說法,若
__enter__()回傳多個值,as後面要怎麼寫 ??
object.__exit__(self, exc_type, exc_value, traceback)-
Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be
None.If an exception is supplied, and the method wishes to SUPPRESS THE EXCEPTION (i.e., prevent it from being propagated), it should return a TRUE VALUE. Otherwise, the exception will be processed normally upon exit from this method.
意指
withcode block 裡有任何 exception 拋出,從__exit__()都會先知道,傳回值會決定 exception 要不要繼續往外拋。 -
Note that
__exit__()methods should not reraise the passed-in exception; this is the caller’s responsibility.
-
-
28.7. contextlib — Utilities for with-statement contexts — Python 2.7.16 documentation #ril
- This module provides utilities for common tasks involving the
withstatement. For more information see also Context Manager Types and With Statement Context Managers.
contextlib.contextmanager(func)-
This function is a DECORATOR that can be used to define a FACTORY FUNCTION for
withstatement context managers, without needing to create a class or separate__enter__()and__exit__()methods.While many objects natively support use in
withstatements, sometimes a resource needs to be managed that isn’t a context manager in its own right, and doesn’t implement aclose()method for use withcontextlib.closing -
An abstract example would be the following to ensure correct resource management:
from contextlib import contextmanager @contextmanager def managed_resource(*args, **kwds): # Code to acquire resource, e.g.: resource = acquire_resource(*args, **kwds) try: yield resource finally: # Code to release resource, e.g.: release_resource(resource) >>> with managed_resource(timeout=3600) as resource: ... # Resource is released at the end of this block, ... # even if code in the block raises an exceptionThe function being decorated must return a GENERATOR-ITERATOR when called. This iterator must YIELD EXACTLY ONE VALUE, which will be bound to the targets in the
withstatement’sasclause, if any. -
At the point where the generator yields, the block nested in the
withstatement is executed. The generator is then resumed after the block is exited.If an unhandled exception occurs in the block, it is RERAISED INSIDE THE GENERATOR AT THE POINT WHERE THE YIELD OCCURRED. Thus, you can use a
try...except...finallystatement to trap the error (if any), or ENSURE THAT SOME CLEANUP TAKES PLACE.If an exception is trapped merely in order to log it or to perform some action (rather than to suppress it entirely), the generator must RERAISE that exception. Otherwise the generator context manager will indicate to the
withstatement that the exception has been handled, and execution will resume with the statement immediately following thewithstatement.
- This module provides utilities for common tasks involving the
-
Python with Context Managers (2016-03-07) #ril
- Context manager 最常見且最重要的用途是管理 resource,這也就是為何用 context manager 來讀取檔案 (
with open('what_are_context_managers.txt', 'r') as infile;讀取檔案會耗費一項資源 -- file descriptor,但這項資源是有限的。在 macOS 或 Linux 跑for x in range(100000): files.append(open('foo.txt', 'w'))可能會遇到OSError: [Errno 24] Too many open files: 'foo.txt'的錯誤 (但為什麼單純做open('foo.txt', 'w')不加入 list 不會有問題??) - 當你開啟一個檔案,OS 會配發一個 integer,做為存取的 handle,這就是 file descriptor。好處是可以在 process 間交換 reference to file,且 kernel 也可以居間要求 security。而 don't leak file descriptors! 中的 leak 指的是 not closing opened files,忘了做
close()可能就會發現一個 process 的 file descriptor 數量是有限的 (ulimit -n),所以只要把數字減個 5 (扣除 Python interpreter 一開始就會開啟的數量),就能引發上面 Too many open files 的問題。 - 實務上很難確保
close()會被呼叫,尤其 function 可能會丟出 exception 或是有多個 return path 時。其他語言得用try...except...finally處理,所幸 Python 提供 context manager 可以確保 resource 有被 clean up,不管 code 成功 return 或是過程中有丟出 exception。
- Context manager 最常見且最重要的用途是管理 resource,這也就是為何用 context manager 來讀取檔案 (
-
5.11. Context Manager Types - 5. Built-in Types — Python 2.7.14 documentation #ril
-
29.6. contextlib — Utilities for with-statement contexts — Python 3.6.6rc1 documentation #ril