# SOME DESCRIPTIVE TITLE. # Copyright (C) 2001-2025, Python Software Foundation # This file is distributed under the same license as the Python package. # FIRST AUTHOR , YEAR. # # Translators: # Rafael Fontenelle , 2025 # #, fuzzy msgid "" msgstr "" "Project-Id-Version: Python 3.12\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-07-25 16:03+0000\n" "PO-Revision-Date: 2025-07-18 19:57+0000\n" "Last-Translator: Rafael Fontenelle , 2025\n" "Language-Team: Chinese (China) (https://app.transifex.com/python-doc/teams/5390/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" #: ../../library/contextlib.rst:2 msgid "" ":mod:`!contextlib` --- Utilities for :keyword:`!with`\\ -statement contexts" msgstr ":mod:`!contextlib` --- 为 :keyword:`!with`\\ 语句上下文提供的工具" #: ../../library/contextlib.rst:7 msgid "**Source code:** :source:`Lib/contextlib.py`" msgstr "**源代码** :source:`Lib/contextlib.py`" #: ../../library/contextlib.rst:11 msgid "" "This module provides utilities for common tasks involving the " ":keyword:`with` statement. For more information see also " ":ref:`typecontextmanager` and :ref:`context-managers`." msgstr "" "此模块为涉及 :keyword:`with` 语句的常见任务提供了实用的工具。更多信息请参见 :ref:`typecontextmanager` 和 " ":ref:`context-managers`。" #: ../../library/contextlib.rst:17 msgid "Utilities" msgstr "工具" #: ../../library/contextlib.rst:19 msgid "Functions and classes provided:" msgstr "提供的函数和类:" #: ../../library/contextlib.rst:23 msgid "" "An :term:`abstract base class` for classes that implement " ":meth:`object.__enter__` and :meth:`object.__exit__`. A default " "implementation for :meth:`object.__enter__` is provided which returns " "``self`` while :meth:`object.__exit__` is an abstract method which by " "default returns ``None``. See also the definition of " ":ref:`typecontextmanager`." msgstr "" "一个为实现了 :meth:`object.__enter__` 与 :meth:`object.__exit__` 的类提供的 " ":term:`abstract base class`。为 :meth:`object.__enter__` 提供的一个默认实现是返回 ``self``" " 而 :meth:`object.__exit__` 是一个默认返回 ``None`` 的抽象方法。 参见 " ":ref:`typecontextmanager` 的定义。" #: ../../library/contextlib.rst:34 msgid "" "An :term:`abstract base class` for classes that implement " ":meth:`object.__aenter__` and :meth:`object.__aexit__`. A default " "implementation for :meth:`object.__aenter__` is provided which returns " "``self`` while :meth:`object.__aexit__` is an abstract method which by " "default returns ``None``. See also the definition of :ref:`async-context-" "managers`." msgstr "" "一个为实现了 :meth:`object.__aenter__` 与 :meth:`object.__aexit__` 的类提供的 " ":term:`abstract base class`。 为 :meth:`object.__aenter__` 提供的一个默认实现是返回 " "``self`` 而 :meth:`object.__aexit__` 是一个默认返回 ``None`` 的抽象方法。 参见 :ref:`async-" "context-managers` 的定义。" #: ../../library/contextlib.rst:46 msgid "" "This function is a :term:`decorator` that can be used to define a factory " "function for :keyword:`with` statement context managers, without needing to " "create a class or separate :meth:`~object.__enter__` and " ":meth:`~object.__exit__` methods." msgstr "" "此函数是一个 :term:`decorator`,它可被用来定义一个支持 :keyword:`with` " "语句上下文管理器的工厂函数,而无需创建一个类或单独的 :meth:`~object.__enter__` 和 " ":meth:`~object.__exit__` 方法。" #: ../../library/contextlib.rst:50 msgid "" "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 with " "``contextlib.closing``" msgstr "" "尽管许多对象原生支持使用 with 语句,但有些需要被管理的资源并不是上下文管理器,并且没有实现 ``close()`` 方法而不能使用 " "``contextlib.closing`` 。" #: ../../library/contextlib.rst:54 msgid "" "An abstract example would be the following to ensure correct resource " "management::" msgstr "下面是一个抽象的示例,展示如何确保正确的资源管理::" #: ../../library/contextlib.rst:57 msgid "" "from contextlib import contextmanager\n" "\n" "@contextmanager\n" "def managed_resource(*args, **kwds):\n" " # Code to acquire resource, e.g.:\n" " resource = acquire_resource(*args, **kwds)\n" " try:\n" " yield resource\n" " finally:\n" " # Code to release resource, e.g.:\n" " release_resource(resource)" msgstr "" "from contextlib import contextmanager\n" "\n" "@contextmanager\n" "def managed_resource(*args, **kwds):\n" " # 获取资源的代码,例如:\n" " resource = acquire_resource(*args, **kwds)\n" " try:\n" " yield resource\n" " finally:\n" " # 释放资源的代码,例如:\n" " release_resource(resource)" #: ../../library/contextlib.rst:69 msgid "The function can then be used like this::" msgstr "随后可以这样使用此函数::" #: ../../library/contextlib.rst:71 msgid "" ">>> with managed_resource(timeout=3600) as resource:\n" "... # Resource is released at the end of this block,\n" "... # even if code in the block raises an exception" msgstr "" ">>> with managed_resource(timeout=3600) as resource:\n" "... # 资源将在此代码块的末尾被释放,\n" "... # 即使代码块中的代码引发了异常" #: ../../library/contextlib.rst:75 msgid "" "The function being decorated must return a :term:`generator`-iterator when " "called. This iterator must yield exactly one value, which will be bound to " "the targets in the :keyword:`with` statement's :keyword:`!as` clause, if " "any." msgstr "" "被装饰的函数在被调用时,必须返回一个 :term:`generator` 迭代器。 这个迭代器必须只 yield 一个值出来,这个值会被用在 " ":keyword:`with` 语句中,绑定到 :keyword:`!as` 后面的变量,如果给定了的话。" #: ../../library/contextlib.rst:79 msgid "" "At the point where the generator yields, the block nested in the " ":keyword:`with` statement 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 :keyword:`try`...\\ :keyword:`except`...\\ :keyword:`finally` " "statement 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 :keyword:`!with` statement that the exception has been " "handled, and execution will resume with the statement immediately following " "the :keyword:`!with` statement." msgstr "" "当生成器发生 yield 时,嵌套在 :keyword:`with` 语句中的语句体会被执行。 语句体执行完毕离开之后,该生成器将被恢复执行。 " "如果在该语句体中发生了未处理的异常,则该异常会在生成器发生 yield 时重新被引发。 因此,你可以使用 :keyword:`try`...\\ " ":keyword:`except`...\\ :keyword:`finally` 语句来捕获该异常(如果有的话),或确保进行了一些清理。 " "如果仅出于记录日志或执行某些操作(而非完全抑制异常)的目的捕获了异常,生成器必须重新引发该异常。 否则生成器的上下文管理器将向 " ":keyword:`!with` 语句指示该异常已经被处理,程序将立即在 :keyword:`!with` 语句之后恢复并继续执行。" #: ../../library/contextlib.rst:91 msgid "" ":func:`contextmanager` uses :class:`ContextDecorator` so the context " "managers it creates can be used as decorators as well as in :keyword:`with` " "statements. 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 :func:`contextmanager` to meet the requirement " "that context managers support multiple invocations in order to be used as " "decorators)." msgstr "" ":func:`contextmanager` 使用 :class:`ContextDecorator` 因此它创建的上下文管理器不仅可以用在 " ":keyword:`with` 语句中,还可以用作一个装饰器。当它用作一个装饰器时,每一次函数调用时都会隐式创建一个新的生成器实例(这使得 " ":func:`contextmanager` 创建的上下文管理器满足了支持多次调用以用作装饰器的需求,而非“一次性”的上下文管理器)。" #: ../../library/contextlib.rst:98 msgid "Use of :class:`ContextDecorator`." msgstr ":class:`ContextDecorator` 的使用。" #: ../../library/contextlib.rst:104 msgid "" "Similar to :func:`~contextlib.contextmanager`, but creates an " ":ref:`asynchronous context manager `." msgstr "" "与 :func:`~contextlib.contextmanager` 类似,但创建的是 :ref:`asynchronous context " "manager ` 。" #: ../../library/contextlib.rst:107 msgid "" "This function is a :term:`decorator` that can be used to define a factory " "function for :keyword:`async with` statement asynchronous context managers, " "without needing to create a class or separate :meth:`~object.__aenter__` and" " :meth:`~object.__aexit__` methods. It must be applied to an " ":term:`asynchronous generator` function." msgstr "" "该函数是一个 :term:`decorator`,它可被用来定义一个使用 :keyword:`async with` " "语句的异步上下文管理器的工厂函数,而不需要创建一个类或单独的 :meth:`~object.__aenter__` 和 " ":meth:`~object.__aexit__` 方法。 它必须应用在 :term:`asynchronous generator` 函数上。" #: ../../library/contextlib.rst:113 msgid "A simple example::" msgstr "一个简单的示例:" #: ../../library/contextlib.rst:115 msgid "" "from contextlib import asynccontextmanager\n" "\n" "@asynccontextmanager\n" "async def get_connection():\n" " conn = await acquire_db_connection()\n" " try:\n" " yield conn\n" " finally:\n" " await release_db_connection(conn)\n" "\n" "async def get_all_users():\n" " async with get_connection() as conn:\n" " return conn.query('SELECT ...')" msgstr "" "from contextlib import asynccontextmanager\n" "\n" "@asynccontextmanager\n" "async def get_connection():\n" " conn = await acquire_db_connection()\n" " try:\n" " yield conn\n" " finally:\n" " await release_db_connection(conn)\n" "\n" "async def get_all_users():\n" " async with get_connection() as conn:\n" " return conn.query('SELECT ...')" #: ../../library/contextlib.rst:131 msgid "" "Context managers defined with :func:`asynccontextmanager` can be used either" " as decorators or with :keyword:`async with` statements::" msgstr "" "使用 :func:`asynccontextmanager` 定义的上下文管理器可以用作装饰器,也可以在 :keyword:`async with` " "语句中使用。" #: ../../library/contextlib.rst:134 msgid "" "import time\n" "from contextlib import asynccontextmanager\n" "\n" "@asynccontextmanager\n" "async def timeit():\n" " now = time.monotonic()\n" " try:\n" " yield\n" " finally:\n" " print(f'it took {time.monotonic() - now}s to run')\n" "\n" "@timeit()\n" "async def main():\n" " # ... async code ..." msgstr "" "import time\n" "from contextlib import asynccontextmanager\n" "\n" "@asynccontextmanager\n" "async def timeit():\n" " now = time.monotonic()\n" " try:\n" " yield\n" " finally:\n" " print(f'it took {time.monotonic() - now}s to run')\n" "\n" "@timeit()\n" "async def main():\n" " # ... 异步代码 ..." #: ../../library/contextlib.rst:149 msgid "" "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 :func:`asynccontextmanager` to meet the requirement that context " "managers support multiple invocations in order to be used as decorators." msgstr "" "用作装饰器时,每次函数调用都会隐式创建一个新的生成器实例。这使得由 :func:`asynccontextmanager` 创建的 “一次性” " "上下文管理器能够满足作为装饰器所需要的支持多次调用的要求。" #: ../../library/contextlib.rst:154 msgid "" "Async context managers created with :func:`asynccontextmanager` can be used " "as decorators." msgstr "使用 :func:`asynccontextmanager` 创建的异步上下文管理器可以用作装饰器。" #: ../../library/contextlib.rst:161 msgid "" "Return a context manager that closes *thing* upon completion of the block. " "This is basically equivalent to::" msgstr "返回一个在语句块执行完成时关闭 *things* 的上下文管理器。这基本上等价于:" #: ../../library/contextlib.rst:164 msgid "" "from contextlib import contextmanager\n" "\n" "@contextmanager\n" "def closing(thing):\n" " try:\n" " yield thing\n" " finally:\n" " thing.close()" msgstr "" "from contextlib import contextmanager\n" "\n" "@contextmanager\n" "def closing(thing):\n" " try:\n" " yield thing\n" " finally:\n" " thing.close()" #: ../../library/contextlib.rst:173 msgid "And lets you write code like this::" msgstr "并允许你编写这样的代码:" #: ../../library/contextlib.rst:175 msgid "" "from contextlib import closing\n" "from urllib.request import urlopen\n" "\n" "with closing(urlopen('https://www.python.org')) as page:\n" " for line in page:\n" " print(line)" msgstr "" "from contextlib import closing\n" "from urllib.request import urlopen\n" "\n" "with closing(urlopen('https://www.python.org')) as page:\n" " for line in page:\n" " print(line)" #: ../../library/contextlib.rst:182 msgid "" "without needing to explicitly close ``page``. Even if an error occurs, " "``page.close()`` will be called when the :keyword:`with` block is exited." msgstr "" "而无需显式地关闭 ``page`` 。 即使发生错误,在退出 :keyword:`with` 语句块时, ``page.close()`` " "也同样会被调用。" #: ../../library/contextlib.rst:187 msgid "" "Most types managing resources support the :term:`context manager` protocol, " "which closes *thing* on leaving the :keyword:`with` statement. As such, " ":func:`!closing` is most useful for third party types that don't support " "context managers. This example is purely for illustration purposes, as " ":func:`~urllib.request.urlopen` would normally be used in a context manager." msgstr "" "大多数管理资源的类型都支持 :term:`context manager` 协议,它在离开 :keyword:`with` 语句时将关闭 " "*thing*。 因此,:func:`!closing` 对不支持上下文管理器的第三方类型是最有用的。 这个例子纯粹是为了说明问题,因为 " ":func:`~urllib.request.urlopen` 通常都会在上下文管理器中使用。" #: ../../library/contextlib.rst:196 msgid "" "Return an async context manager that calls the ``aclose()`` method of " "*thing* upon completion of the block. This is basically equivalent to::" msgstr "返回一个在语句块执行完成时调用 ``aclose()`` 方法来关闭 *things* 的异步上下文管理器。这基本上等价于:" #: ../../library/contextlib.rst:199 msgid "" "from contextlib import asynccontextmanager\n" "\n" "@asynccontextmanager\n" "async def aclosing(thing):\n" " try:\n" " yield thing\n" " finally:\n" " await thing.aclose()" msgstr "" "from contextlib import asynccontextmanager\n" "\n" "@asynccontextmanager\n" "async def aclosing(thing):\n" " try:\n" " yield thing\n" " finally:\n" " await thing.aclose()" #: ../../library/contextlib.rst:208 msgid "" "Significantly, ``aclosing()`` supports deterministic cleanup of async " "generators when they happen to exit early by :keyword:`break` or an " "exception. For example::" msgstr "" "重要的是,``aclosing()`` 支持在异步生成器因遭遇 :keyword:`break` 或异常而提前退出时对其执行确定性的清理。 例如::" #: ../../library/contextlib.rst:212 msgid "" "from contextlib import aclosing\n" "\n" "async with aclosing(my_generator()) as values:\n" " async for value in values:\n" " if value == 42:\n" " break" msgstr "" "from contextlib import aclosing\n" "\n" "async with aclosing(my_generator()) as values:\n" " async for value in values:\n" " if value == 42:\n" " break" #: ../../library/contextlib.rst:219 msgid "" "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)." msgstr "" "此模块将确保生成器的异步退出代码在与其迭代相同的上下文中执行(这样异常和上下文变量将能按预期工作,并且退出代码不会在其所依赖的某些任务的生命期结束后继续运行)。" #: ../../library/contextlib.rst:231 msgid "" "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::" msgstr "" "返回一个从 ``__enter__`` 返回 *enter_result* " "的上下文管理器,除此之外不执行任何操作。它旨在用于可选上下文管理器的一种替代,例如:" #: ../../library/contextlib.rst:235 msgid "" "def myfunction(arg, ignore_exceptions=False):\n" " if ignore_exceptions:\n" " # Use suppress to ignore all exceptions.\n" " cm = contextlib.suppress(Exception)\n" " else:\n" " # Do not ignore any exceptions, cm has no effect.\n" " cm = contextlib.nullcontext()\n" " with cm:\n" " # Do something" msgstr "" "def myfunction(arg, ignore_exceptions=False):\n" " if ignore_exceptions:\n" " # 使用 suppress 来忽略所有异常。\n" " cm = contextlib.suppress(Exception)\n" " else:\n" " # 不忽略任何异常,cm 将没有影响。\n" " cm = contextlib.nullcontext()\n" " with cm:\n" " # 执行某些操作" #: ../../library/contextlib.rst:245 msgid "An example using *enter_result*::" msgstr "一个使用 *enter_result* 的例子:" #: ../../library/contextlib.rst:247 msgid "" "def process_file(file_or_path):\n" " if isinstance(file_or_path, str):\n" " # If string, open file\n" " cm = open(file_or_path)\n" " else:\n" " # Caller is responsible for closing file\n" " cm = nullcontext(file_or_path)\n" "\n" " with cm as file:\n" " # Perform processing on the file" msgstr "" "def process_file(file_or_path):\n" " if isinstance(file_or_path, str):\n" " # If string, open file\n" " cm = open(file_or_path)\n" " else:\n" " # 调用方要负责关闭文件\n" " cm = nullcontext(file_or_path)\n" "\n" " with cm as file:\n" " # 在文件上执行处理" #: ../../library/contextlib.rst:258 msgid "" "It can also be used as a stand-in for :ref:`asynchronous context managers " "`::" msgstr "" "它也可以替代 :ref:`asynchronous context managers ` :" #: ../../library/contextlib.rst:261 msgid "" "async def send_http(session=None):\n" " if not session:\n" " # If no http session, create it with aiohttp\n" " cm = aiohttp.ClientSession()\n" " else:\n" " # Caller is responsible for closing the session\n" " cm = nullcontext(session)\n" "\n" " async with cm as session:\n" " # Send http requests with session" msgstr "" "async def send_http(session=None):\n" " if not session:\n" " # 如果没有 http 会话,则使用 aiohttp 创建它\n" " cm = aiohttp.ClientSession()\n" " else:\n" " # 调用方要负责关闭会话\n" " cm = nullcontext(session)\n" "\n" " async with cm as session:\n" " # 使用会话发送 http 请求" #: ../../library/contextlib.rst:274 msgid ":term:`asynchronous context manager` support was added." msgstr "增加了对 :term:`asynchronous context manager` 的支持。" #: ../../library/contextlib.rst:281 msgid "" "Return a context manager that suppresses any of the specified exceptions if " "they occur in the body of a :keyword:`!with` statement and then resumes " "execution with the first statement following the end of the :keyword:`!with`" " statement." msgstr "" "返回一个当指定的异常在 :keyword:`!with` 语句体中发生时会屏蔽它们然后从 :keyword:`!with` " "语句结束后的第一条语言开始恢复执行的上下文管理器。" #: ../../library/contextlib.rst:286 msgid "" "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." msgstr "与完全抑制异常的任何其他机制一样,该上下文管理器应当只用来抑制非常具体的错误,并确保该场景下静默地继续执行程序是通用的正确做法。" #: ../../library/contextlib.rst:291 msgid "For example::" msgstr "例如:" #: ../../library/contextlib.rst:293 msgid "" "from contextlib import suppress\n" "\n" "with suppress(FileNotFoundError):\n" " os.remove('somefile.tmp')\n" "\n" "with suppress(FileNotFoundError):\n" " os.remove('someotherfile.tmp')" msgstr "" "from contextlib import suppress\n" "\n" "with suppress(FileNotFoundError):\n" " os.remove('somefile.tmp')\n" "\n" "with suppress(FileNotFoundError):\n" " os.remove('someotherfile.tmp')" #: ../../library/contextlib.rst:301 msgid "This code is equivalent to::" msgstr "这段代码等价于:" #: ../../library/contextlib.rst:303 msgid "" "try:\n" " os.remove('somefile.tmp')\n" "except FileNotFoundError:\n" " pass\n" "\n" "try:\n" " os.remove('someotherfile.tmp')\n" "except FileNotFoundError:\n" " pass" msgstr "" "try:\n" " os.remove('somefile.tmp')\n" "except FileNotFoundError:\n" " pass\n" "\n" "try:\n" " os.remove('someotherfile.tmp')\n" "except FileNotFoundError:\n" " pass" #: ../../library/contextlib.rst:313 ../../library/contextlib.rst:362 #: ../../library/contextlib.rst:372 ../../library/contextlib.rst:389 msgid "This context manager is :ref:`reentrant `." msgstr "该上下文管理器是 :ref:`reentrant ` 。" #: ../../library/contextlib.rst:315 msgid "" "If the code within the :keyword:`!with` block raises a " ":exc:`BaseExceptionGroup`, suppressed exceptions are removed from the group." " Any exceptions of the group which are not suppressed are re-raised in a " "new group which is created using the original group's " ":meth:`~BaseExceptionGroup.derive` method." msgstr "" "如果 :keyword:`!with` 语句块内的代码引发了 :exc:`BaseExceptionGroup`,将从分组中移除被抑制的异常。 " "该分组中任何未被抑制的异常会在一个使用原分组的 :meth:`~BaseExceptionGroup.derive` 方法创建的新分组中被重新引发。" #: ../../library/contextlib.rst:323 msgid "" "``suppress`` now supports suppressing exceptions raised as part of a " ":exc:`BaseExceptionGroup`." msgstr "``suppress`` 现在支持抑制作为 :exc:`BaseExceptionGroup` 的组成部分被引发的异常。" #: ../../library/contextlib.rst:329 msgid "" "Context manager for temporarily redirecting :data:`sys.stdout` to another " "file or file-like object." msgstr "用于将 :data:`sys.stdout` 临时重定向到一个文件或类文件对象的上下文管理器。" #: ../../library/contextlib.rst:332 msgid "" "This tool adds flexibility to existing functions or classes whose output is " "hardwired to stdout." msgstr "该工具给已有的将输出硬编码写到 stdout 的函数或类提供了额外的灵活性。" #: ../../library/contextlib.rst:335 msgid "" "For example, the output of :func:`help` normally is sent to *sys.stdout*. " "You can capture that output in a string by redirecting the output to an " ":class:`io.StringIO` object. The replacement stream is returned from the " "``__enter__`` method and so is available as the target of the " ":keyword:`with` statement::" msgstr "" "例如, :func:`help` 的输出通常会被发送到 *sys.stdout*。 你可以通过将输出重定向到一个 " ":class:`io.StringIO` 对象来将该输出捕获到字符串。 替换的流是由 ``__enter__`` 返回的因此可以被用作 " ":keyword:`with` 语句的目标::" #: ../../library/contextlib.rst:341 msgid "" "with redirect_stdout(io.StringIO()) as f:\n" " help(pow)\n" "s = f.getvalue()" msgstr "" "with redirect_stdout(io.StringIO()) as f:\n" " help(pow)\n" "s = f.getvalue()" #: ../../library/contextlib.rst:345 msgid "" "To send the output of :func:`help` to a file on disk, redirect the output to" " a regular file::" msgstr "如果要把 :func:`help` 的输出写到磁盘上的一个文件,重定向该输出到一个常规文件:" #: ../../library/contextlib.rst:348 msgid "" "with open('help.txt', 'w') as f:\n" " with redirect_stdout(f):\n" " help(pow)" msgstr "" "with open('help.txt', 'w') as f:\n" " with redirect_stdout(f):\n" " help(pow)" #: ../../library/contextlib.rst:352 msgid "To send the output of :func:`help` to *sys.stderr*::" msgstr "如果要把 :func:`help` 的输出写到 *sys.stderr* :" #: ../../library/contextlib.rst:354 msgid "" "with redirect_stdout(sys.stderr):\n" " help(pow)" msgstr "" "with redirect_stdout(sys.stderr):\n" " help(pow)" #: ../../library/contextlib.rst:357 msgid "" "Note that the global side effect on :data:`sys.stdout` means that this " "context manager is not suitable for use in library code and most threaded " "applications. It also has no effect on the output of subprocesses. However, " "it is still a useful approach for many utility scripts." msgstr "" "需要注意的点在于, :data:`sys.stdout` " "的全局副作用意味着此上下文管理器不适合在库代码和大多数多线程应用程序中使用。它对子进程的输出没有影响。不过对于许多工具脚本而言,它仍然是一个有用的方法。" #: ../../library/contextlib.rst:369 msgid "" "Similar to :func:`~contextlib.redirect_stdout` but redirecting " ":data:`sys.stderr` to another file or file-like object." msgstr "" "与 :func:`~contextlib.redirect_stdout` 类似,不过是将 :data:`sys.stderr` " "重定向到一个文件或类文件对象。" #: ../../library/contextlib.rst:379 msgid "" "Non parallel-safe context manager to change the current working directory. " "As this changes a global state, the working directory, it is not suitable " "for use in most threaded or async contexts. It is also not suitable for most" " non-linear code execution, like generators, where the program execution is " "temporarily relinquished -- unless explicitly desired, you should not yield " "when this context manager is active." msgstr "" "用于改变当前工作目录的非并行安全的上下文管理器。 由于这会改变一个全局状态,即工作目录,因此它不适合在大多数线程或异步上下文中使用。 " "它也不适合大多数非线性的代码执行,比如生成器,在此类代码中程序的执行会被临时性挂起 -- 除非明确希望如此,当该上下文管理器被激活时你不应执行 " "yield 语句。" #: ../../library/contextlib.rst:386 msgid "" "This is a simple wrapper around :func:`~os.chdir`, it changes the current " "working directory upon entering and restores the old one on exit." msgstr "这是一个对 :func:`~os.chdir` 的简单包装器,它会在进入时改变当前工作目录并在退出时恢复。" #: ../../library/contextlib.rst:396 msgid "" "A base class that enables a context manager to also be used as a decorator." msgstr "一个使上下文管理器能用作装饰器的基类。" #: ../../library/contextlib.rst:398 msgid "" "Context managers inheriting from ``ContextDecorator`` have to implement " "``__enter__`` and ``__exit__`` as normal. ``__exit__`` retains its optional " "exception handling even when used as a decorator." msgstr "" "与往常一样,继承自 ``ContextDecorator``  的上下文管理器必须实现 ``__enter__`` 与 ``__exit__`` " "。即使用作装饰器, ``__exit__`` 依旧会保持可能的异常处理。" #: ../../library/contextlib.rst:402 msgid "" "``ContextDecorator`` is used by :func:`contextmanager`, so you get this " "functionality automatically." msgstr "``ContextDecorator`` 被用在 :func:`contextmanager` 中,因此你自然获得了这项功能。" #: ../../library/contextlib.rst:405 msgid "Example of ``ContextDecorator``::" msgstr "``ContextDecorator`` 的示例::" #: ../../library/contextlib.rst:407 msgid "" "from contextlib import ContextDecorator\n" "\n" "class mycontext(ContextDecorator):\n" " def __enter__(self):\n" " print('Starting')\n" " return self\n" "\n" " def __exit__(self, *exc):\n" " print('Finishing')\n" " return False" msgstr "" "from contextlib import ContextDecorator\n" "\n" "class mycontext(ContextDecorator):\n" " def __enter__(self):\n" " print('Starting')\n" " return self\n" "\n" " def __exit__(self, *exc):\n" " print('Finishing')\n" " return False" #: ../../library/contextlib.rst:418 ../../library/contextlib.rst:490 msgid "The class can then be used like this::" msgstr "随后可以这样使用该类::" #: ../../library/contextlib.rst:420 msgid "" ">>> @mycontext()\n" "... def function():\n" "... print('The bit in the middle')\n" "...\n" ">>> function()\n" "Starting\n" "The bit in the middle\n" "Finishing\n" "\n" ">>> with mycontext():\n" "... print('The bit in the middle')\n" "...\n" "Starting\n" "The bit in the middle\n" "Finishing" msgstr "" ">>> @mycontext()\n" "... def function():\n" "... print('The bit in the middle')\n" "...\n" ">>> function()\n" "Starting\n" "The bit in the middle\n" "Finishing\n" "\n" ">>> with mycontext():\n" "... print('The bit in the middle')\n" "...\n" "Starting\n" "The bit in the middle\n" "Finishing" #: ../../library/contextlib.rst:436 msgid "" "This change is just syntactic sugar for any construct of the following " "form::" msgstr "这个改动只是针对如下形式的一个语法糖:" #: ../../library/contextlib.rst:438 msgid "" "def f():\n" " with cm():\n" " # Do stuff" msgstr "" "def f():\n" " with cm():\n" " # 执行操作" #: ../../library/contextlib.rst:442 msgid "``ContextDecorator`` lets you instead write::" msgstr "``ContextDecorator`` 使得你可以这样改写:" #: ../../library/contextlib.rst:444 msgid "" "@cm()\n" "def f():\n" " # Do stuff" msgstr "" "@cm()\n" "def f():\n" " # 执行操作" #: ../../library/contextlib.rst:448 msgid "" "It makes it clear that the ``cm`` applies to the whole function, rather than" " just a piece of it (and saving an indentation level is nice, too)." msgstr "这能清楚地表明, ``cm`` 作用于整个函数,而不仅仅是函数的一部分(同时也能保持不错的缩进层级)。" #: ../../library/contextlib.rst:451 msgid "" "Existing context managers that already have a base class can be extended by " "using ``ContextDecorator`` as a mixin class::" msgstr "现有的上下文管理器即使已经有基类,也可以使用 ``ContextDecorator`` 作为混合类进行扩展:" #: ../../library/contextlib.rst:454 msgid "" "from contextlib import ContextDecorator\n" "\n" "class mycontext(ContextBaseClass, ContextDecorator):\n" " def __enter__(self):\n" " return self\n" "\n" " def __exit__(self, *exc):\n" " return False" msgstr "" "from contextlib import ContextDecorator\n" "\n" "class mycontext(ContextBaseClass, ContextDecorator):\n" " def __enter__(self):\n" " return self\n" "\n" " def __exit__(self, *exc):\n" " return False" #: ../../library/contextlib.rst:464 msgid "" "As the decorated function must be able to be called multiple times, the " "underlying context manager must support use in multiple :keyword:`with` " "statements. If this is not the case, then the original construct with the " "explicit :keyword:`!with` statement inside the function should be used." msgstr "" "由于被装饰的函数必须能够被多次调用,因此对应的上下文管理器必须支持在多个 :keyword:`with` " "语句中使用。如果不是这样,则应当使用原来的具有显式 :keyword:`!with` 语句的形式使用该上下文管理器。" #: ../../library/contextlib.rst:474 msgid "" "Similar to :class:`ContextDecorator` but only for asynchronous functions." msgstr "和 :class:`ContextDecorator` 类似,但是用于异步函数。" #: ../../library/contextlib.rst:476 msgid "Example of ``AsyncContextDecorator``::" msgstr "``AsyncContextDecorator`` 的示例::" #: ../../library/contextlib.rst:478 msgid "" "from asyncio import run\n" "from contextlib import AsyncContextDecorator\n" "\n" "class mycontext(AsyncContextDecorator):\n" " async def __aenter__(self):\n" " print('Starting')\n" " return self\n" "\n" " async def __aexit__(self, *exc):\n" " print('Finishing')\n" " return False" msgstr "" "from asyncio import run\n" "from contextlib import AsyncContextDecorator\n" "\n" "class mycontext(AsyncContextDecorator):\n" " async def __aenter__(self):\n" " print('Starting')\n" " return self\n" "\n" " async def __aexit__(self, *exc):\n" " print('Finishing')\n" " return False" #: ../../library/contextlib.rst:492 msgid "" ">>> @mycontext()\n" "... async def function():\n" "... print('The bit in the middle')\n" "...\n" ">>> run(function())\n" "Starting\n" "The bit in the middle\n" "Finishing\n" "\n" ">>> async def function():\n" "... async with mycontext():\n" "... print('The bit in the middle')\n" "...\n" ">>> run(function())\n" "Starting\n" "The bit in the middle\n" "Finishing" msgstr "" ">>> @mycontext()\n" "... async def function():\n" "... print('The bit in the middle')\n" "...\n" ">>> run(function())\n" "Starting\n" "The bit in the middle\n" "Finishing\n" "\n" ">>> async def function():\n" "... async with mycontext():\n" "... print('The bit in the middle')\n" "...\n" ">>> run(function())\n" "Starting\n" "The bit in the middle\n" "Finishing" #: ../../library/contextlib.rst:515 msgid "" "A context manager that is designed to make it easy to programmatically " "combine other context managers and cleanup functions, especially those that " "are optional or otherwise driven by input data." msgstr "该上下文管理器的设计目标是使得在编码中组合其他上下文管理器和清理函数更加容易,尤其是那些可选的或由输入数据驱动的上下文管理器。" #: ../../library/contextlib.rst:519 msgid "" "For example, a set of files may easily be handled in a single with statement" " as follows::" msgstr "例如,通过一个如下的 with 语句可以很容易处理一组文件:" #: ../../library/contextlib.rst:522 msgid "" "with ExitStack() as stack:\n" " files = [stack.enter_context(open(fname)) for fname in filenames]\n" " # All opened files will automatically be closed at the end of\n" " # the with statement, even if attempts to open files later\n" " # in the list raise an exception" msgstr "" "with ExitStack() as stack:\n" " files = [stack.enter_context(open(fname)) for fname in filenames]\n" " # 所有已打开的文件都将在 with 语句结束时\n" " # 自动被关闭,即使此后打开列表中文件的\n" " # 尝试引发了异常" #: ../../library/contextlib.rst:528 msgid "" "The :meth:`~object.__enter__` method returns the :class:`ExitStack` " "instance, and performs no additional operations." msgstr ":meth:`~object.__enter__` 方法返回 :class:`ExitStack` 的实例,并且不会执行额外的操作。" #: ../../library/contextlib.rst:531 msgid "" "Each instance maintains a stack of registered callbacks that are called in " "reverse order when the instance is closed (either explicitly or implicitly " "at the end of a :keyword:`with` statement). Note that callbacks are *not* " "invoked implicitly when the context stack instance is garbage collected." msgstr "" "每个实例维护一个注册了一组回调的栈,这些回调在实例关闭时以相反的顺序被调用(显式或隐式地在 :keyword:`with` " "语句的末尾)。请注意,当一个栈实例被垃圾回收时,这些回调将 *不会* 被隐式调用。" #: ../../library/contextlib.rst:536 msgid "" "This stack model is used so that context managers that acquire their " "resources in their ``__init__`` method (such as file objects) can be handled" " correctly." msgstr "通过使用这个基于栈的模型,那些通过 ``__init__`` 方法获取资源的上下文管理器(如文件对象)能够被正确处理。" #: ../../library/contextlib.rst:540 msgid "" "Since registered callbacks are invoked in the reverse order of registration," " this ends up behaving as if multiple nested :keyword:`with` statements had " "been used with the registered set of callbacks. This even extends to " "exception handling - if an inner callback suppresses or replaces an " "exception, then outer callbacks will be passed arguments based on that " "updated state." msgstr "" "由于注册的回调函数是按照与注册相反的顺序调用的,因此最终的行为就像多个嵌套的 :keyword:`with` " "语句用在这些注册的回调函数上。这个行为甚至扩展到了异常处理:如果内部的回调函数抑制或替换了异常,则外部回调收到的参数是基于该更新后的状态得到的。" #: ../../library/contextlib.rst:547 msgid "" "This is a relatively low level API that takes care of the details of " "correctly unwinding the stack of exit callbacks. It provides a suitable " "foundation for higher level context managers that manipulate the exit stack " "in application specific ways." msgstr "" "这是一个相对底层的 " "API,它负责正确处理栈里回调退出时依次展开的细节。它为相对高层的上下文管理器提供了一个合适的基础,使得它能根据应用程序的需求使用特定方式操作栈。" #: ../../library/contextlib.rst:556 msgid "" "Enters a new context manager and adds its :meth:`~object.__exit__` method to" " the callback stack. The return value is the result of the context manager's" " own :meth:`~object.__enter__` method." msgstr "" "进入一个新的上下文管理器并将其 :meth:`~object.__exit__` 方法添加到回调栈中。 返回值是该上下文管理器自己的 " ":meth:`~object.__enter__` 方法的输出结果。" #: ../../library/contextlib.rst:560 msgid "" "These context managers may suppress exceptions just as they normally would " "if used directly as part of a :keyword:`with` statement." msgstr "这些上下文管理器可能会屏蔽异常就如当它们作为 :keyword:`with` 语句的一部分直接使用时通常表现的行为一样。" #: ../../library/contextlib.rst:563 msgid "" "Raises :exc:`TypeError` instead of :exc:`AttributeError` if *cm* is not a " "context manager." msgstr "如果 *cm* 不是上下文管理器则会引发 :exc:`TypeError` 而不是 :exc:`AttributeError`。" #: ../../library/contextlib.rst:569 msgid "" "Adds a context manager's :meth:`~object.__exit__` method to the callback " "stack." msgstr "将一个上下文管理器的 :meth:`~object.__exit__` 方法添加到回调栈。" #: ../../library/contextlib.rst:571 msgid "" "As ``__enter__`` is *not* invoked, this method can be used to cover part of " "an :meth:`~object.__enter__` implementation with a context manager's own " ":meth:`~object.__exit__` method." msgstr "" "由于 ``__enter__`` *没有* 被唤起,此方法可以被用来通过一个上下文管理器自己的 :meth:`~object.__exit__` " "方法覆盖一部分 :meth:`~object.__enter__` 的实现。" #: ../../library/contextlib.rst:575 msgid "" "If passed an object that is not a context manager, this method assumes it is" " a callback with the same signature as a context manager's " ":meth:`~object.__exit__` method and adds it directly to the callback stack." msgstr "" "如果传入了一个不是上下文管理器的对象,此方法将假定它是一个具有与上下文管理器的 :meth:`~object.__exit__` " "方法相同的签名的回调并会直接将其添加到回调栈中。" #: ../../library/contextlib.rst:579 msgid "" "By returning true values, these callbacks can suppress exceptions the same " "way context manager :meth:`~object.__exit__` methods can." msgstr "通过返回真值,这些回调可以通过与上下文管理器的 :meth:`~object.__exit__` 方法相同的方式抑制异常。" #: ../../library/contextlib.rst:582 msgid "" "The passed in object is returned from the function, allowing this method to " "be used as a function decorator." msgstr "传入的对象将被该函数返回,允许此方法作为函数装饰器使用。" #: ../../library/contextlib.rst:587 msgid "" "Accepts an arbitrary callback function and arguments and adds it to the " "callback stack." msgstr "接受一个任意的回调函数和参数并将其添加到回调栈。" #: ../../library/contextlib.rst:590 msgid "" "Unlike the other methods, callbacks added this way cannot suppress " "exceptions (as they are never passed the exception details)." msgstr "与其他方法不同,通过此方式添加的回调无法屏蔽异常(因为异常的细节不会被传递给它们)。" #: ../../library/contextlib.rst:593 msgid "" "The passed in callback is returned from the function, allowing this method " "to be used as a function decorator." msgstr "传入的回调将被该函数返回,允许此方法作为函数装饰器使用。" #: ../../library/contextlib.rst:598 msgid "" "Transfers the callback stack to a fresh :class:`ExitStack` instance and " "returns it. No callbacks are invoked by this operation - instead, they will " "now be invoked when the new stack is closed (either explicitly or implicitly" " at the end of a :keyword:`with` statement)." msgstr "" "将回调栈传输到一个新的 :class:`ExitStack` 实例并返回它。 此操作不会唤起任何回调 —— " "作为替代,现在当新栈被关闭时它们将(显式地或是在一条 :keyword:`with` 语句结束时隐式地)被唤起。" #: ../../library/contextlib.rst:603 msgid "" "For example, a group of files can be opened as an \"all or nothing\" " "operation as follows::" msgstr "例如,一组文件可以像下面这样以“一个都不能少”的操作方式被打开::" #: ../../library/contextlib.rst:606 msgid "" "with ExitStack() as stack:\n" " files = [stack.enter_context(open(fname)) for fname in filenames]\n" " # Hold onto the close method, but don't call it yet.\n" " close_files = stack.pop_all().close\n" " # If opening any file fails, all previously opened files will be\n" " # closed automatically. If all files are opened successfully,\n" " # they will remain open even after the with statement ends.\n" " # close_files() can then be invoked explicitly to close them all." msgstr "" "with ExitStack() as stack:\n" " files = [stack.enter_context(open(fname)) for fname in filenames]\n" " # 持有 close 方法,但暂时不调用它。\n" " close_files = stack.pop_all().close\n" " # 如果任何文件打开失败,则所有之前打开的文件\n" " # 将自动被关闭。 如果所有文件都被成功地打开,\n" " # 即使在 with 语句结束后它们仍将保持打开状态。\n" " # 随后可以显式唤起 close_files() 来全部关闭它们。" #: ../../library/contextlib.rst:617 msgid "" "Immediately unwinds the callback stack, invoking callbacks in the reverse " "order of registration. For any context managers and exit callbacks " "registered, the arguments passed in will indicate that no exception " "occurred." msgstr "立即展开回调栈,按注册时的相反顺序唤起其中的回调。 对于任何已注册的上下文管理器和退出回调,传入的参数将表明没有发生异常。" #: ../../library/contextlib.rst:624 msgid "" "An :ref:`asynchronous context manager `, similar to " ":class:`ExitStack`, that supports combining both synchronous and " "asynchronous context managers, as well as having coroutines for cleanup " "logic." msgstr "" "一个 :ref:`异步上下文管理器 `,类似于 " ":class:`ExitStack`,它支持组合同步和异步上下文管理器,并拥有针对清理逻辑的协程。" #: ../../library/contextlib.rst:629 msgid "" "The :meth:`~ExitStack.close` method is not implemented; :meth:`aclose` must " "be used instead." msgstr ":meth:`~ExitStack.close` 方法未实现,必须改用 :meth:`aclose`。" #: ../../library/contextlib.rst:635 msgid "" "Similar to :meth:`ExitStack.enter_context` but expects an asynchronous " "context manager." msgstr "类似于 :meth:`ExitStack.enter_context` 但是需要一个异步上下文管理器。" #: ../../library/contextlib.rst:638 msgid "" "Raises :exc:`TypeError` instead of :exc:`AttributeError` if *cm* is not an " "asynchronous context manager." msgstr "如果 *cm* 不是异步上下文管理器则会引发 :exc:`TypeError` 而不是 :exc:`AttributeError`。" #: ../../library/contextlib.rst:644 msgid "" "Similar to :meth:`ExitStack.push` but expects either an asynchronous context" " manager or a coroutine function." msgstr "类似于 :meth:`ExitStack.push` 但是需要一个异步上下文管理器或协程函数。" #: ../../library/contextlib.rst:649 msgid "" "Similar to :meth:`ExitStack.callback` but expects a coroutine function." msgstr "类似于 :meth:`ExitStack.callback` 但是需要一个协程函数。" #: ../../library/contextlib.rst:654 msgid "Similar to :meth:`ExitStack.close` but properly handles awaitables." msgstr "类似于 :meth:`ExitStack.close` 但是能正确处理可等待对象。" #: ../../library/contextlib.rst:656 msgid "Continuing the example for :func:`asynccontextmanager`::" msgstr "从 :func:`asynccontextmanager` 的例子继续:" #: ../../library/contextlib.rst:658 msgid "" "async with AsyncExitStack() as stack:\n" " connections = [await stack.enter_async_context(get_connection())\n" " for i in range(5)]\n" " # All opened connections will automatically be released at the end of\n" " # the async with statement, even if attempts to open a connection\n" " # later in the list raise an exception." msgstr "" "async with AsyncExitStack() as stack:\n" " connections = [await stack.enter_async_context(get_connection())\n" " for i in range(5)]\n" " # 所有已打开连接都将在 async with 语句结束时\n" " # 自动被关闭,即使此后打开列表中连接的尝试\n" " # 引发了异常。" #: ../../library/contextlib.rst:668 msgid "Examples and Recipes" msgstr "例子和配方" #: ../../library/contextlib.rst:670 msgid "" "This section describes some examples and recipes for making effective use of" " the tools provided by :mod:`contextlib`." msgstr "本节描述了一些用于有效利用 :mod:`contextlib` 所提供的工具的示例和步骤说明。" #: ../../library/contextlib.rst:675 msgid "Supporting a variable number of context managers" msgstr "支持可变数量的上下文管理器" #: ../../library/contextlib.rst:677 msgid "" "The primary use case for :class:`ExitStack` is the one given in the class " "documentation: supporting a variable number of context managers and other " "cleanup operations in a single :keyword:`with` statement. The variability " "may come from the number of context managers needed being driven by user " "input (such as opening a user specified collection of files), or from some " "of the context managers being optional::" msgstr "" ":class:`ExitStack` 的主要应用场景已在该类的文档中给出:在单个 :keyword:`with` " "语句中支持可变数量的上下文管理器和其他清理操作。 " "这个可变性可以来自通过用户输入驱动所需的上下文管理器数量(例如打开用户所指定的文件集),或者来自将某些上下文管理器作为可选项。" #: ../../library/contextlib.rst:684 msgid "" "with ExitStack() as stack:\n" " for resource in resources:\n" " stack.enter_context(resource)\n" " if need_special_resource():\n" " special = acquire_special_resource()\n" " stack.callback(release_special_resource, special)\n" " # Perform operations that use the acquired resources" msgstr "" "with ExitStack() as stack:\n" " for resource in resources:\n" " stack.enter_context(resource)\n" " if need_special_resource():\n" " special = acquire_special_resource()\n" " stack.callback(release_special_resource, special)\n" " # 执行使用了所获取资源的操作" #: ../../library/contextlib.rst:692 msgid "" "As shown, :class:`ExitStack` also makes it quite easy to use :keyword:`with`" " statements to manage arbitrary resources that don't natively support the " "context management protocol." msgstr "" "如上所示,:class:`ExitStack` 还让使用 :keyword:`with` 语句来管理任意非原生支持上下文管理协议的资源变得相当容易。" #: ../../library/contextlib.rst:698 msgid "Catching exceptions from ``__enter__`` methods" msgstr "捕获 ``__enter__`` 方法产生的异常" #: ../../library/contextlib.rst:700 msgid "" "It is occasionally desirable to catch exceptions from an ``__enter__`` " "method implementation, *without* inadvertently catching exceptions from the " ":keyword:`with` statement body or the context manager's ``__exit__`` method." " By using :class:`ExitStack` the steps in the context management protocol " "can be separated slightly in order to allow this::" msgstr "" "有时人们会想要从 ``__enter__`` 方法的实现中捕获异常,而 *不会* 无意中捕获来自 :keyword:`with` 语句体或上下文管理器的" " ``__exit__`` 方法的异常。 通过使用 :class:`ExitStack` 可以将上下文管理协议中的步骤稍微分开以允许这样做::" #: ../../library/contextlib.rst:706 msgid "" "stack = ExitStack()\n" "try:\n" " x = stack.enter_context(cm)\n" "except Exception:\n" " # handle __enter__ exception\n" "else:\n" " with stack:\n" " # Handle normal case" msgstr "" "stack = ExitStack()\n" "try:\n" " x = stack.enter_context(cm)\n" "except Exception:\n" " # 处理 __enter__ 异常\n" "else:\n" " with stack:\n" " # 处理正常情况" #: ../../library/contextlib.rst:715 msgid "" "Actually needing to do this is likely to indicate that the underlying API " "should be providing a direct resource management interface for use with " ":keyword:`try`/:keyword:`except`/:keyword:`finally` statements, but not all " "APIs are well designed in that regard. When a context manager is the only " "resource management API provided, then :class:`ExitStack` can make it easier" " to handle various situations that can't be handled directly in a " ":keyword:`with` statement." msgstr "" "实际上需要这样做很可能表明下层的 API 应该提供一个直接的资源管理接口以便与 " ":keyword:`try`/:keyword:`except`/:keyword:`finally` 语句配合使用,但并不是所有的 API " "在这方面都设计得很好。 当上下文管理器是所提供的唯一资源管理 API 时,则 :class:`ExitStack` 可以让处理各种无法在 " ":keyword:`with` 语句中直接处理的情况变得更为容易。" #: ../../library/contextlib.rst:725 msgid "Cleaning up in an ``__enter__`` implementation" msgstr "在一个 ``__enter__`` 方法的实现中进行清理" #: ../../library/contextlib.rst:727 msgid "" "As noted in the documentation of :meth:`ExitStack.push`, this method can be " "useful in cleaning up an already allocated resource if later steps in the " ":meth:`~object.__enter__` implementation fail." msgstr "" "正如 :meth:`ExitStack.push` 的文档中指出的,如果在 :meth:`~object.__enter__` " "实现中的后续步骤失败则此方法将可被用于清理已分配的资源。" #: ../../library/contextlib.rst:731 msgid "" "Here's an example of doing this for a context manager that accepts resource " "acquisition and release functions, along with an optional validation " "function, and maps them to the context management protocol::" msgstr "下面是为一个上下文管理器做这件事的例子,该上下文管理器可接受资源获取和释放函数,以及可选的验证函数,并将它们映射到上下文管理协议::" #: ../../library/contextlib.rst:735 msgid "" "from contextlib import contextmanager, AbstractContextManager, ExitStack\n" "\n" "class ResourceManager(AbstractContextManager):\n" "\n" " def __init__(self, acquire_resource, release_resource, check_resource_ok=None):\n" " self.acquire_resource = acquire_resource\n" " self.release_resource = release_resource\n" " if check_resource_ok is None:\n" " def check_resource_ok(resource):\n" " return True\n" " self.check_resource_ok = check_resource_ok\n" "\n" " @contextmanager\n" " def _cleanup_on_error(self):\n" " with ExitStack() as stack:\n" " stack.push(self)\n" " yield\n" " # The validation check passed and didn't raise an exception\n" " # Accordingly, we want to keep the resource, and pass it\n" " # back to our caller\n" " stack.pop_all()\n" "\n" " def __enter__(self):\n" " resource = self.acquire_resource()\n" " with self._cleanup_on_error():\n" " if not self.check_resource_ok(resource):\n" " msg = \"Failed validation for {!r}\"\n" " raise RuntimeError(msg.format(resource))\n" " return resource\n" "\n" " def __exit__(self, *exc_details):\n" " # We don't need to duplicate any of our resource release logic\n" " self.release_resource()" msgstr "" "from contextlib import contextmanager, AbstractContextManager, ExitStack\n" "\n" "class ResourceManager(AbstractContextManager):\n" "\n" " def __init__(self, acquire_resource, release_resource, check_resource_ok=None):\n" " self.acquire_resource = acquire_resource\n" " self.release_resource = release_resource\n" " if check_resource_ok is None:\n" " def check_resource_ok(resource):\n" " return True\n" " self.check_resource_ok = check_resource_ok\n" "\n" " @contextmanager\n" " def _cleanup_on_error(self):\n" " with ExitStack() as stack:\n" " stack.push(self)\n" " yield\n" " # 验证检测通过且没有引发异常\n" " # 相应地,我们想要保留资源,并将其\n" " # 回传给调用方\n" " stack.pop_all()\n" "\n" " def __enter__(self):\n" " resource = self.acquire_resource()\n" " with self._cleanup_on_error():\n" " if not self.check_resource_ok(resource):\n" " msg = \"Failed validation for {!r}\"\n" " raise RuntimeError(msg.format(resource))\n" " return resource\n" "\n" " def __exit__(self, *exc_details):\n" " # 我们不需要复制任何的资源释放逻辑\n" " self.release_resource()" #: ../../library/contextlib.rst:771 msgid "Replacing any use of ``try-finally`` and flag variables" msgstr "替换任何对 ``try-finally`` 和旗标变量的使用" #: ../../library/contextlib.rst:773 msgid "" "A pattern you will sometimes see is a ``try-finally`` statement with a flag " "variable to indicate whether or not the body of the ``finally`` clause " "should be executed. In its simplest form (that can't already be handled just" " by using an ``except`` clause instead), it looks something like this::" msgstr "" "一种你有时将看到的模式是 ``try-finally`` 语句附带一个旗标变量来指明 ``finally`` 子句体是否要被执行。 " "在其最简单的形式中(它无法仅仅通过改用一条 ``except`` 子句来预先处理),看起来会是这样::" #: ../../library/contextlib.rst:778 msgid "" "cleanup_needed = True\n" "try:\n" " result = perform_operation()\n" " if result:\n" " cleanup_needed = False\n" "finally:\n" " if cleanup_needed:\n" " cleanup_resources()" msgstr "" "cleanup_needed = True\n" "try:\n" " result = perform_operation()\n" " if result:\n" " cleanup_needed = False\n" "finally:\n" " if cleanup_needed:\n" " cleanup_resources()" #: ../../library/contextlib.rst:787 msgid "" "As with any ``try`` statement based code, this can cause problems for " "development and review, because the setup code and the cleanup code can end " "up being separated by arbitrarily long sections of code." msgstr "就如任何基于 ``try`` 语句的代码一样,这可能会导致开发和审查方面的问题,因为设置代码和清理代码最终可能会被任意长的代码部分所分隔。" #: ../../library/contextlib.rst:791 msgid "" ":class:`ExitStack` makes it possible to instead register a callback for " "execution at the end of a ``with`` statement, and then later decide to skip " "executing that callback::" msgstr "" ":class:`ExitStack` 将允许选择在一条 ``with`` 语句末尾注册一个用于执行的回调的替代方式,等以后再决定是否跳过该回调的执行::" #: ../../library/contextlib.rst:795 msgid "" "from contextlib import ExitStack\n" "\n" "with ExitStack() as stack:\n" " stack.callback(cleanup_resources)\n" " result = perform_operation()\n" " if result:\n" " stack.pop_all()" msgstr "" "from contextlib import ExitStack\n" "\n" "with ExitStack() as stack:\n" " stack.callback(cleanup_resources)\n" " result = perform_operation()\n" " if result:\n" " stack.pop_all()" #: ../../library/contextlib.rst:803 msgid "" "This allows the intended cleanup behaviour to be made explicit up front, " "rather than requiring a separate flag variable." msgstr "这允许在事先显式地指明预期的清理行为,而不需要一个单独的旗标变量。" #: ../../library/contextlib.rst:806 msgid "" "If a particular application uses this pattern a lot, it can be simplified " "even further by means of a small helper class::" msgstr "如果某个应用程序大量使用此模式,则可以通过使用一个较小的辅助类来进一步地简化它::" #: ../../library/contextlib.rst:809 msgid "" "from contextlib import ExitStack\n" "\n" "class Callback(ExitStack):\n" " def __init__(self, callback, /, *args, **kwds):\n" " super().__init__()\n" " self.callback(callback, *args, **kwds)\n" "\n" " def cancel(self):\n" " self.pop_all()\n" "\n" "with Callback(cleanup_resources) as cb:\n" " result = perform_operation()\n" " if result:\n" " cb.cancel()" msgstr "" "from contextlib import ExitStack\n" "\n" "class Callback(ExitStack):\n" " def __init__(self, callback, /, *args, **kwds):\n" " super().__init__()\n" " self.callback(callback, *args, **kwds)\n" "\n" " def cancel(self):\n" " self.pop_all()\n" "\n" "with Callback(cleanup_resources) as cb:\n" " result = perform_operation()\n" " if result:\n" " cb.cancel()" #: ../../library/contextlib.rst:824 msgid "" "If the resource cleanup isn't already neatly bundled into a standalone " "function, then it is still possible to use the decorator form of " ":meth:`ExitStack.callback` to declare the resource cleanup in advance::" msgstr "" "如果资源清理操作尚未完善地捆绑到一个独立的函数中,则仍然可以使用 :meth:`ExitStack.callback` " "的装饰器形式来提前声明资源清理::" #: ../../library/contextlib.rst:829 msgid "" "from contextlib import ExitStack\n" "\n" "with ExitStack() as stack:\n" " @stack.callback\n" " def cleanup_resources():\n" " ...\n" " result = perform_operation()\n" " if result:\n" " stack.pop_all()" msgstr "" "from contextlib import ExitStack\n" "\n" "with ExitStack() as stack:\n" " @stack.callback\n" " def cleanup_resources():\n" " ...\n" " result = perform_operation()\n" " if result:\n" " stack.pop_all()" #: ../../library/contextlib.rst:839 msgid "" "Due to the way the decorator protocol works, a callback function declared " "this way cannot take any parameters. Instead, any resources to be released " "must be accessed as closure variables." msgstr "受装饰器协议工作方式的影响,以此方式声明的回调函数无法接受任何形参。 作为替代,任何要释放的资源必须作为闭包变量来访问。" #: ../../library/contextlib.rst:845 msgid "Using a context manager as a function decorator" msgstr "将上下文管理器作为函数装饰器使用" #: ../../library/contextlib.rst:847 msgid "" ":class:`ContextDecorator` makes it possible to use a context manager in both" " an ordinary ``with`` statement and also as a function decorator." msgstr ":class:`ContextDecorator` 类允许将上下文管理器作为函数装饰器使用,而不仅在 ``with`` 语句块中使用。" #: ../../library/contextlib.rst:850 msgid "" "For example, it is sometimes useful to wrap functions or groups of " "statements with a logger that can track the time of entry and time of exit." " Rather than writing both a function decorator and a context manager for " "the task, inheriting from :class:`ContextDecorator` provides both " "capabilities in a single definition::" msgstr "" "例如,有时将函数或语句组包装在一个可以跟踪进入和退出时间的记录器中是很有用的。 与其为任务同时编写函数装饰器和上下文管理器,不如继承 " ":class:`ContextDecorator` 在一个定义中同时提供这两种能力::" #: ../../library/contextlib.rst:856 msgid "" "from contextlib import ContextDecorator\n" "import logging\n" "\n" "logging.basicConfig(level=logging.INFO)\n" "\n" "class track_entry_and_exit(ContextDecorator):\n" " def __init__(self, name):\n" " self.name = name\n" "\n" " def __enter__(self):\n" " logging.info('Entering: %s', self.name)\n" "\n" " def __exit__(self, exc_type, exc, exc_tb):\n" " logging.info('Exiting: %s', self.name)" msgstr "" "from contextlib import ContextDecorator\n" "import logging\n" "\n" "logging.basicConfig(level=logging.INFO)\n" "\n" "class track_entry_and_exit(ContextDecorator):\n" " def __init__(self, name):\n" " self.name = name\n" "\n" " def __enter__(self):\n" " logging.info('Entering: %s', self.name)\n" "\n" " def __exit__(self, exc_type, exc, exc_tb):\n" " logging.info('Exiting: %s', self.name)" #: ../../library/contextlib.rst:871 msgid "Instances of this class can be used as both a context manager::" msgstr "这个类的实例既可以被用作上下文管理器:" #: ../../library/contextlib.rst:873 msgid "" "with track_entry_and_exit('widget loader'):\n" " print('Some time consuming activity goes here')\n" " load_widget()" msgstr "" "with track_entry_and_exit('widget loader'):\n" " print('Some time consuming activity goes here')\n" " load_widget()" #: ../../library/contextlib.rst:877 msgid "And also as a function decorator::" msgstr "也可以被用作函数装饰器:" #: ../../library/contextlib.rst:879 msgid "" "@track_entry_and_exit('widget loader')\n" "def activity():\n" " print('Some time consuming activity goes here')\n" " load_widget()" msgstr "" "@track_entry_and_exit('widget loader')\n" "def activity():\n" " print('Some time consuming activity goes here')\n" " load_widget()" #: ../../library/contextlib.rst:884 msgid "" "Note that there is one additional limitation when using context managers as " "function decorators: there's no way to access the return value of " ":meth:`~object.__enter__`. If that value is needed, then it is still " "necessary to use an explicit ``with`` statement." msgstr "" "请注意当使用上下文管理器作为函数装饰器时有一个额外的限制:没有任何办法可以访问 :meth:`~object.__enter__` 的返回值。 " "如果需要该值,那么你仍然需要使用显式的 ``with`` 语句。" #: ../../library/contextlib.rst:891 msgid ":pep:`343` - The \"with\" statement" msgstr ":pep:`343` - \"with\" 语句" #: ../../library/contextlib.rst:892 msgid "" "The specification, background, and examples for the Python :keyword:`with` " "statement." msgstr "Python :keyword:`with` 语句的规范描述、背景和示例。" #: ../../library/contextlib.rst:898 msgid "Single use, reusable and reentrant context managers" msgstr "单独使用,可重用并可重进入的上下文管理器" #: ../../library/contextlib.rst:900 msgid "" "Most context managers are written in a way that means they can only be used " "effectively in a :keyword:`with` statement once. These single use context " "managers must be created afresh each time they're used - attempting to use " "them a second time will trigger an exception or otherwise not work " "correctly." msgstr "" "大多数上下文管理器的编写方式意味着它们只能在一个 :keyword:`with` 语句中被有效使用一次。 " "这些一次性使用的上下文管理器必须在每次被使用时重新创建 —— 试图第二次使用它们将会触发异常或是不能正确工作。" #: ../../library/contextlib.rst:906 msgid "" "This common limitation means that it is generally advisable to create " "context managers directly in the header of the :keyword:`with` statement " "where they are used (as shown in all of the usage examples above)." msgstr "" "这个常见的限制意味着通常来说都建议在 :keyword:`with` 语句开头上下文管理器被使用的位置直接创建它们(如下面所有的使用示例所显示的)。" #: ../../library/contextlib.rst:910 msgid "" "Files are an example of effectively single use context managers, since the " "first :keyword:`with` statement will close the file, preventing any further " "IO operations using that file object." msgstr "" "文件是一个高效的单次使用上下文管理器的例子,因为第一个 :keyword:`with` 语句将关闭文件,防止任何后续的使用该文件对象的 IO 操作。" #: ../../library/contextlib.rst:914 msgid "" "Context managers created using :func:`contextmanager` are also single use " "context managers, and will complain about the underlying generator failing " "to yield if an attempt is made to use them a second time::" msgstr "" "使用 :func:`contextmanager` " "创建的上下文管理器也是单次使用的上下文管理器,并会在试图第二次使用它们时报告下层生成器无法执行产生操作::" #: ../../library/contextlib.rst:918 msgid "" ">>> from contextlib import contextmanager\n" ">>> @contextmanager\n" "... def singleuse():\n" "... print(\"Before\")\n" "... yield\n" "... print(\"After\")\n" "...\n" ">>> cm = singleuse()\n" ">>> with cm:\n" "... pass\n" "...\n" "Before\n" "After\n" ">>> with cm:\n" "... pass\n" "...\n" "Traceback (most recent call last):\n" " ...\n" "RuntimeError: generator didn't yield" msgstr "" ">>> from contextlib import contextmanager\n" ">>> @contextmanager\n" "... def singleuse():\n" "... print(\"Before\")\n" "... yield\n" "... print(\"After\")\n" "...\n" ">>> cm = singleuse()\n" ">>> with cm:\n" "... pass\n" "...\n" "Before\n" "After\n" ">>> with cm:\n" "... pass\n" "...\n" "Traceback (most recent call last):\n" " ...\n" "RuntimeError: generator didn't yield" #: ../../library/contextlib.rst:942 msgid "Reentrant context managers" msgstr "重进入上下文管理器" #: ../../library/contextlib.rst:944 msgid "" "More sophisticated context managers may be \"reentrant\". These context " "managers can not only be used in multiple :keyword:`with` statements, but " "may also be used *inside* a :keyword:`!with` statement that is already using" " the same context manager." msgstr "" "更复杂的上下文管理器可以“重进入”。 这些上下文管理器不但可以被用于多个 :keyword:`with` " "语句中,还可以被用于已经在使用同一个上下文管理器的 :keyword:`!with` 语句 *内部*。" #: ../../library/contextlib.rst:949 msgid "" ":class:`threading.RLock` is an example of a reentrant context manager, as " "are :func:`suppress`, :func:`redirect_stdout`, and :func:`chdir`. Here's a " "very simple example of reentrant use::" msgstr "" ":class:`threading.RLock` 是一个可重入上下文管理器的例子,:func:`suppress`, " ":func:`redirect_stdout` 和 :func:`chdir` 也是。 下面是一个非常简单的使用重入的示例::" #: ../../library/contextlib.rst:953 msgid "" ">>> from contextlib import redirect_stdout\n" ">>> from io import StringIO\n" ">>> stream = StringIO()\n" ">>> write_to_stream = redirect_stdout(stream)\n" ">>> with write_to_stream:\n" "... print(\"This is written to the stream rather than stdout\")\n" "... with write_to_stream:\n" "... print(\"This is also written to the stream\")\n" "...\n" ">>> print(\"This is written directly to stdout\")\n" "This is written directly to stdout\n" ">>> print(stream.getvalue())\n" "This is written to the stream rather than stdout\n" "This is also written to the stream" msgstr "" ">>> from contextlib import redirect_stdout\n" ">>> from io import StringIO\n" ">>> stream = StringIO()\n" ">>> write_to_stream = redirect_stdout(stream)\n" ">>> with write_to_stream:\n" "... print(\"This is written to the stream rather than stdout\")\n" "... with write_to_stream:\n" "... print(\"This is also written to the stream\")\n" "...\n" ">>> print(\"This is written directly to stdout\")\n" "This is written directly to stdout\n" ">>> print(stream.getvalue())\n" "This is written to the stream rather than stdout\n" "This is also written to the stream" #: ../../library/contextlib.rst:968 msgid "" "Real world examples of reentrancy are more likely to involve multiple " "functions calling each other and hence be far more complicated than this " "example." msgstr "现实世界的可重入例子更可能涉及到多个函数的相互调用因此会比这个例子要复杂得多。" #: ../../library/contextlib.rst:972 msgid "" "Note also that being reentrant is *not* the same thing as being thread safe." " :func:`redirect_stdout`, for example, is definitely not thread safe, as it " "makes a global modification to the system state by binding " ":data:`sys.stdout` to a different stream." msgstr "" "还要注意可重入与线程安全 *不是* 一回事。 举例来说,:func:`redirect_stdout` 肯定不是线程安全的,因为它会通过将 " ":data:`sys.stdout` 绑定到一个不同的流对系统状态做了全局性的修改。" #: ../../library/contextlib.rst:981 msgid "Reusable context managers" msgstr "可重用的上下文管理器" #: ../../library/contextlib.rst:983 msgid "" "Distinct from both single use and reentrant context managers are " "\"reusable\" context managers (or, to be completely explicit, \"reusable, " "but not reentrant\" context managers, since reentrant context managers are " "also reusable). These context managers support being used multiple times, " "but will fail (or otherwise not work correctly) if the specific context " "manager instance has already been used in a containing with statement." msgstr "" "与单次使用和可重入上下文管理器都不同的还有“可重用”上下文管理器(或者,使用完全显式的表达应为“可重用,但不可重入”上下文管理器,因为可重入上下文管理器也会是可重用的)。" " 这些上下文管理器支持多次使用,但如果特定的上下文管理器实例已经在包含它的 with 语句中被使用过则将失败(或者不能正确工作)。" #: ../../library/contextlib.rst:990 msgid "" ":class:`threading.Lock` is an example of a reusable, but not reentrant, " "context manager (for a reentrant lock, it is necessary to use " ":class:`threading.RLock` instead)." msgstr "" ":class:`threading.Lock` 是一个可重用,但是不可重入的上下文管理器的例子(对于可重入锁,则有必要使用 " ":class:`threading.RLock` 来代替)。" #: ../../library/contextlib.rst:994 msgid "" "Another example of a reusable, but not reentrant, context manager is " ":class:`ExitStack`, as it invokes *all* currently registered callbacks when " "leaving any with statement, regardless of where those callbacks were added::" msgstr "" "另一个可重用,但不可重入的上下文管理器的例子是 :class:`ExitStack`,因为它在离开任何 with 语句时会唤起 *所有* " "当前已注册的回调,不论回调是在哪里添加的::" #: ../../library/contextlib.rst:999 msgid "" ">>> from contextlib import ExitStack\n" ">>> stack = ExitStack()\n" ">>> with stack:\n" "... stack.callback(print, \"Callback: from first context\")\n" "... print(\"Leaving first context\")\n" "...\n" "Leaving first context\n" "Callback: from first context\n" ">>> with stack:\n" "... stack.callback(print, \"Callback: from second context\")\n" "... print(\"Leaving second context\")\n" "...\n" "Leaving second context\n" "Callback: from second context\n" ">>> with stack:\n" "... stack.callback(print, \"Callback: from outer context\")\n" "... with stack:\n" "... stack.callback(print, \"Callback: from inner context\")\n" "... print(\"Leaving inner context\")\n" "... print(\"Leaving outer context\")\n" "...\n" "Leaving inner context\n" "Callback: from inner context\n" "Callback: from outer context\n" "Leaving outer context" msgstr "" ">>> from contextlib import ExitStack\n" ">>> stack = ExitStack()\n" ">>> with stack:\n" "... stack.callback(print, \"Callback: from first context\")\n" "... print(\"Leaving first context\")\n" "...\n" "Leaving first context\n" "Callback: from first context\n" ">>> with stack:\n" "... stack.callback(print, \"Callback: from second context\")\n" "... print(\"Leaving second context\")\n" "...\n" "Leaving second context\n" "Callback: from second context\n" ">>> with stack:\n" "... stack.callback(print, \"Callback: from outer context\")\n" "... with stack:\n" "... stack.callback(print, \"Callback: from inner context\")\n" "... print(\"Leaving inner context\")\n" "... print(\"Leaving outer context\")\n" "...\n" "Leaving inner context\n" "Callback: from inner context\n" "Callback: from outer context\n" "Leaving outer context" #: ../../library/contextlib.rst:1025 msgid "" "As the output from the example shows, reusing a single stack object across " "multiple with statements works correctly, but attempting to nest them will " "cause the stack to be cleared at the end of the innermost with statement, " "which is unlikely to be desirable behaviour." msgstr "" "正如这个例子的输出所显示的,在多个 with 语句中重用一个单独的栈对象可以正确工作,但调试嵌套它们就将导致栈在最内层的 with " "语句结束时被清空,这不大可能是符合期望的行为。" #: ../../library/contextlib.rst:1030 msgid "" "Using separate :class:`ExitStack` instances instead of reusing a single " "instance avoids that problem::" msgstr "使用单独的 :class:`ExitStack` 实例而不是重复使用一个实例可以避免此问题::" #: ../../library/contextlib.rst:1033 msgid "" ">>> from contextlib import ExitStack\n" ">>> with ExitStack() as outer_stack:\n" "... outer_stack.callback(print, \"Callback: from outer context\")\n" "... with ExitStack() as inner_stack:\n" "... inner_stack.callback(print, \"Callback: from inner context\")\n" "... print(\"Leaving inner context\")\n" "... print(\"Leaving outer context\")\n" "...\n" "Leaving inner context\n" "Callback: from inner context\n" "Leaving outer context\n" "Callback: from outer context" msgstr "" ">>> from contextlib import ExitStack\n" ">>> with ExitStack() as outer_stack:\n" "... outer_stack.callback(print, \"Callback: from outer context\")\n" "... with ExitStack() as inner_stack:\n" "... inner_stack.callback(print, \"Callback: from inner context\")\n" "... print(\"Leaving inner context\")\n" "... print(\"Leaving outer context\")\n" "...\n" "Leaving inner context\n" "Callback: from inner context\n" "Leaving outer context\n" "Callback: from outer context"