contextlib --- with 陳述式工具程式¶
This module provides utilities for common tasks involving the with
statement. For more information see also 情境管理器型別 and
With 陳述式的情境管理器.
Utilities¶
Functions and classes provided:
- class contextlib.AbstractContextManager¶
An abstract base class for classes that implement
__enter__()and__exit__(). A default implementation for__enter__()is provided which returnsselfwhile__exit__()is an abstract method which by default returnsNone. See also the definition of 情境管理器型別.在 3.6 版被加入.
- class contextlib.AbstractAsyncContextManager¶
An abstract base class for classes that implement
__aenter__()and__aexit__(). A default implementation for__aenter__()is provided which returnsselfwhile__aexit__()is an abstract method which by default returnsNone. See also the definition of Asynchronous Context Managers.在 3.7 版被加入.
- @contextlib.contextmanager¶
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 with statements, sometimes a resource needs to be managed that isn't a context manager in its own right, and doesn't implement a
close()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)
The function can then be used like this:
>>> with managed_resource(timeout=3600) as resource: ... # Resource is released at the end of this block, ... # even if code in the block raises an exception
The 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 atry...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 thewithstatement that the exception has been handled, and execution will resume with the statement immediately following thewithstatement.contextmanager()usesContextDecoratorso the context managers it creates can be used as decorators as well as inwithstatements. When used as a decorator, a new generator instance is implicitly created on each function call (this allows the otherwise "one-shot" context managers created bycontextmanager()to meet the requirement that context managers support multiple invocations in order to be used as decorators).在 3.2 版的變更: Use of
ContextDecorator.
- @contextlib.asynccontextmanager¶
Similar to
contextmanager(), but creates an asynchronous context manager.This function is a decorator that can be used to define a factory function for
async withstatement asynchronous context managers, without needing to create a class or separate__aenter__()and__aexit__()methods. It must be applied to an asynchronous generator function.一個簡單範例:
from contextlib import asynccontextmanager @asynccontextmanager async def get_connection(): conn = await acquire_db_connection() try: yield conn finally: await release_db_connection(conn) async def get_all_users(): async with get_connection() as conn: return conn.query('SELECT ...')
在 3.7 版被加入.
Context managers defined with
asynccontextmanager()can be used either as decorators or withasync withstatements:import time from contextlib import asynccontextmanager @asynccontextmanager async def timeit(): now = time.monotonic() try: yield finally: print(f'it took {time.monotonic() - now}s to run') @timeit() async def main(): # ... async code ...
When used as a decorator, a new generator instance is implicitly created on each function call. This allows the otherwise "one-shot" context managers created by
asynccontextmanager()to meet the requirement that context managers support multiple invocations in order to be used as decorators.在 3.10 版的變更: Async context managers created with
asynccontextmanager()can be used as decorators.
- contextlib.closing(thing)¶
Return a context manager that closes thing upon completion of the block. This is basically equivalent to:
from contextlib import contextmanager @contextmanager def closing(thing): try: yield thing finally: thing.close()
And lets you write code like this:
from contextlib import closing from urllib.request import urlopen with closing(urlopen('https://www.python.org')) as page: for line in page: print(line)
without needing to explicitly close
page. Even if an error occurs,page.close()will be called when thewithblock is exited.備註
Most types managing resources support the context manager protocol, which closes thing on leaving the
withstatement. As such,closing()is most useful for third party types that don't support context managers. This example is purely for illustration purposes, asurlopen()would normally be used in a context manager.
- contextlib.aclosing(thing)¶
Return an async context manager that calls the
aclose()method of thing upon completion of the block. This is basically equivalent to:from contextlib import asynccontextmanager @asynccontextmanager async def aclosing(thing): try: yield thing finally: await thing.aclose()
Significantly,
aclosing()supports deterministic cleanup of async generators when they happen to exit early bybreakor an exception. For example:from contextlib import aclosing async with aclosing(my_generator()) as values: async for value in values: if value == 42: break
This pattern ensures that the generator's async exit code is executed in the same context as its iterations (so that exceptions and context variables work as expected, and the exit code isn't run after the lifetime of some task it depends on).
在 3.10 版被加入.
- contextlib.nullcontext(enter_result=None)¶
Return a context manager that returns enter_result from
__enter__(), but otherwise does nothing. It is intended to be used as a stand-in for an optional context manager, for example:def myfunction(arg, ignore_exceptions=False): if ignore_exceptions: # Use suppress to ignore all exceptions. cm = contextlib.suppress(Exception) else: # Do not ignore any exceptions, cm has no effect. cm = contextlib.nullcontext() with cm: # Do something
一個使用 enter_result 的範例:
def process_file(file_or_path): if isinstance(file_or_path, str): # If string, open file cm = open(file_or_path) else: # Caller is responsible for closing file cm = nullcontext(file_or_path) with cm as file: # Perform processing on the file
It can also be used as a stand-in for asynchronous context managers:
async def send_http(session=None): if not session: # If no http session, create it with aiohttp cm = aiohttp.ClientSession() else: # Caller is responsible for closing the session cm = nullcontext(session) async with cm as session: # Send http requests with session
在 3.7 版被加入.
在 3.10 版的變更: asynchronous context manager support was added.
- contextlib.suppress(*exceptions)¶
Return a context manager that suppresses any of the specified exceptions if they occur in the body of a
withstatement and then resumes execution with the first statement following the end of thewithstatement.As with any other mechanism that completely suppresses exceptions, this context manager should be used only to cover very specific errors where silently continuing with program execution is known to be the right thing to do.
舉例來說:
from contextlib import suppress with suppress(FileNotFoundError