# Copyright (C) 2001 Python Software Foundation # This file is distributed under the same license as the Python package. # # Translators: # Adrian Liaw , 2018 # Matt Wang , 2022 msgid "" msgstr "" "Project-Id-Version: Python 3.14\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2026-03-22 00:20+0000\n" "PO-Revision-Date: 2023-02-18 14:17+0800\n" "Last-Translator: Matt Wang \n" "Language-Team: Chinese - TAIWAN (https://github.com/python/python-docs-zh-" "tw)\n" "Language: zh_TW\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" "X-Generator: Poedit 3.2.2\n" #: ../../library/asyncio-dev.rst:7 msgid "Developing with asyncio" msgstr "使用 asyncio 開發" #: ../../library/asyncio-dev.rst:9 msgid "" "Asynchronous programming is different from classic \"sequential\" " "programming." msgstr "" "非同步程式設計 (asynchronous programming) 與傳統的\"順序\"程式設計 " "(sequential programming) 不同。" #: ../../library/asyncio-dev.rst:12 msgid "" "This page lists common mistakes and traps and explains how to avoid them." msgstr "本頁列出常見的錯誤和陷阱,並解釋如何避免它們。" #: ../../library/asyncio-dev.rst:19 msgid "Debug Mode" msgstr "除錯模式" #: ../../library/asyncio-dev.rst:21 msgid "" "By default asyncio runs in production mode. In order to ease the " "development asyncio has a *debug mode*." msgstr "" "在預設情況下 asyncio 以正式生產模式 (production mode) 執行。為了讓開發更輕" "鬆,asyncio 還有一種\\ *除錯模式 (debug mode)*。" #: ../../library/asyncio-dev.rst:24 msgid "There are several ways to enable asyncio debug mode:" msgstr "有幾種方法可以啟用 asyncio 除錯模式:" #: ../../library/asyncio-dev.rst:26 msgid "Setting the :envvar:`PYTHONASYNCIODEBUG` environment variable to ``1``." msgstr "將 :envvar:`PYTHONASYNCIODEBUG` 環境變數設定為 ``1``。" #: ../../library/asyncio-dev.rst:28 msgid "Using the :ref:`Python Development Mode `." msgstr "使用 :ref:`Python 開發模式 (Development Mode) `。" #: ../../library/asyncio-dev.rst:30 msgid "Passing ``debug=True`` to :func:`asyncio.run`." msgstr "將 ``debug=True`` 傳遞給 :func:`asyncio.run`。" #: ../../library/asyncio-dev.rst:32 msgid "Calling :meth:`loop.set_debug`." msgstr "呼叫 :meth:`loop.set_debug`。" #: ../../library/asyncio-dev.rst:34 msgid "In addition to enabling the debug mode, consider also:" msgstr "除了啟用除錯模式外,還要考慮:" #: ../../library/asyncio-dev.rst:36 msgid "" "setting the log level of the :ref:`asyncio logger ` to :py:" "const:`logging.DEBUG`, for example the following snippet of code can be run " "at startup of the application::" msgstr "" "將 :ref:`asyncio logger(日誌記錄器) `\\ 的日誌級别設置為 :" "py:const:`logging.DEBUG`,例如下面的程式片段可以在應用程式啟動時運行: ::" #: ../../library/asyncio-dev.rst:40 msgid "logging.basicConfig(level=logging.DEBUG)" msgstr "logging.basicConfig(level=logging.DEBUG)" #: ../../library/asyncio-dev.rst:42 msgid "" "configuring the :mod:`warnings` module to display :exc:`ResourceWarning` " "warnings. One way of doing that is by using the :option:`-W` ``default`` " "command line option." msgstr "" "配置 :mod:`warnings` 模組以顯示 :exc:`ResourceWarning` 警告。一種方法是使用 :" "option:`-W` ``default`` 命令列選項。" #: ../../library/asyncio-dev.rst:47 msgid "When the debug mode is enabled:" msgstr "啟用除錯模式時:" #: ../../library/asyncio-dev.rst:49 msgid "" "Many non-threadsafe asyncio APIs (such as :meth:`loop.call_soon` and :meth:" "`loop.call_at` methods) raise an exception if they are called from a wrong " "thread." msgstr "" "許多非執行緒安全 (non-threadsafe) 的 asyncio APIs(例如 :meth:`loop." "call_soon` 和 :meth:`loop.call_at` 方法),如果從錯誤的執行緒呼叫就會引發例" "外。" #: ../../library/asyncio-dev.rst:53 msgid "" "The execution time of the I/O selector is logged if it takes too long to " "perform an I/O operation." msgstr "" "如果執行一個 I/O 操作花費的時間太長,則將 I/O 選擇器 (selector) 的執行時間記" "錄到日誌中。" #: ../../library/asyncio-dev.rst:56 msgid "" "Callbacks taking longer than 100 milliseconds are logged. The :attr:`loop." "slow_callback_duration` attribute can be used to set the minimum execution " "duration in seconds that is considered \"slow\"." msgstr "" "執行時間超過 100 毫秒的回呼 (callback) 將會被記錄於日誌。屬性 :attr:`loop." "slow_callback_duration` 可用於設定以秒為單位的最小執行持續時間,超過這個值執" "行時間就會被視為\"緩慢\"。" #: ../../library/asyncio-dev.rst:64 msgid "Concurrency and Multithreading" msgstr "並行性和多執行緒 (Concurrency and Multithreading)" #: ../../library/asyncio-dev.rst:66 msgid "" "An event loop runs in a thread (typically the main thread) and executes all " "callbacks and Tasks in its thread. While a Task is running in the event " "loop, no other Tasks can run in the same thread. When a Task executes an " "``await`` expression, the running Task gets suspended, and the event loop " "executes the next Task." msgstr "" "事件迴圈在執行緒中運行(通常是主執行緒),並在其執行緒中執行所有回呼和 Tasks" "(任務)。當一個 Task 在事件迴圈中運行時,沒有其他 Task 可以在同一個執行緒中" "運行。當一個 Task 執行一個 ``await`` 運算式時,正在執行的 Task 會被暫停,而事" "件迴圈會執行下一個 Task。" #: ../../library/asyncio-dev.rst:72 msgid "" "To schedule a :term:`callback` from another OS thread, the :meth:`loop." "call_soon_threadsafe` method should be used. Example::" msgstr "" "要從不同的 OS 執行緒為一個 :term:`callback` 排程,應該使用 :meth:`loop." "call_soon_threadsafe` 方法。例如: ::" #: ../../library/asyncio-dev.rst:75 msgid "loop.call_soon_threadsafe(callback, *args)" msgstr "loop.call_soon_threadsafe(callback, *args)" #: ../../library/asyncio-dev.rst:77 msgid "" "Almost all asyncio objects are not thread safe, which is typically not a " "problem unless there is code that works with them from outside of a Task or " "a callback. If there's a need for such code to call a low-level asyncio " "API, the :meth:`loop.call_soon_threadsafe` method should be used, e.g.::" msgstr "" "幾乎所有 asyncio 物件都不支援執行緒安全 (thread safe),這通常不是問題,除非" "在 Task 或回呼函式之外有程式需要和它們一起運作。如果需要這樣的程式來呼叫低階 " "asyncio API,應該使用 :meth:`loop.call_soon_threadsafe` 方法,例如: ::" #: ../../library/asyncio-dev.rst:83 msgid "loop.call_soon_threadsafe(fut.cancel)" msgstr "loop.call_soon_threadsafe(fut.cancel)" #: ../../library/asyncio-dev.rst:85 msgid "" "To schedule a coroutine object from a different OS thread, the :func:" "`run_coroutine_threadsafe` function should be used. It returns a :class:" "`concurrent.futures.Future` to access the result::" msgstr "" "要從不同的 OS 執行緒為一個協程物件排程,應該使用 :func:" "`run_coroutine_threadsafe` 函式。它會回傳一個 :class:`concurrent.futures." "Future` 以存取結果: ::" #: ../../library/asyncio-dev.rst:89 msgid "" "async def coro_func():\n" " return await asyncio.sleep(1, 42)\n" "\n" "# Later in another OS thread:\n" "\n" "future = asyncio.run_coroutine_threadsafe(coro_func(), loop)\n" "# Wait for the result:\n" "result = future.result()" msgstr "" "async def coro_func():\n" " return await asyncio.sleep(1, 42)\n" "\n" "# 之後在另一個 OS 執行緒中:\n" "\n" "future = asyncio.run_coroutine_threadsafe(coro_func(), loop)\n" "# 等待結果:\n" "result = future.result()" #: ../../library/asyncio-dev.rst:98 msgid "To handle signals the event loop must be run in the main thread." msgstr "為了能夠處理訊號,事件迴圈必須於主執行緒中運行。" #: ../../library/asyncio-dev.rst:101 msgid "" "The :meth:`loop.run_in_executor` method can be used with a :class:" "`concurrent.futures.ThreadPoolExecutor` or :class:`~concurrent.futures." "InterpreterPoolExecutor` to execute blocking code in a different OS thread " "without blocking the OS thread that the event loop runs in." msgstr "" ":meth:`loop.run_in_executor` 方法可以和 :class:`concurrent.futures." "ThreadPoolExecutor` 或 :class:`~concurrent.futures.InterpreterPoolExecutor` " "一起使用,這能夠在作業系統上另一個不同的執行緒中執行阻塞程式,且避免阻塞執行" "事件迴圈的執行緒。" #: ../../library/asyncio-dev.rst:107 msgid "" "There is currently no way to schedule coroutines or callbacks directly from " "a different process (such as one started with :mod:`multiprocessing`). The :" "ref:`asyncio-event-loop-methods` section lists APIs that can read from pipes " "and watch file descriptors without blocking the event loop. In addition, " "asyncio's :ref:`Subprocess ` APIs provide a way to start " "a process and communicate with it from the event loop. Lastly, the " "aforementioned :meth:`loop.run_in_executor` method can also be used with a :" "class:`concurrent.futures.ProcessPoolExecutor` to execute code in a " "different process." msgstr "" "目前沒有什麼辦法能直接從另一個行程(例如透過 :mod:`multiprocessing` 啟動的程" "序)來為協程或回呼排程。:ref:`asyncio-event-loop-methods`\\ 小節列出了可以從 " "pipes(管道)讀取並監視 file descriptor(檔案描述器)而不會阻塞事件迴圈的 " "API。此外,asyncio 的\\ :ref:`子行程 ` API 提供了一種啟動" "行程並從事件迴圈與其通訊的辦法。最後,之前提到的 :meth:`loop." "run_in_executor` 方法也可和 :class:`concurrent.futures.ProcessPoolExecutor` " "搭配使用,以在另一個行程中執行程式。" #: ../../library/asyncio-dev.rst:121 msgid "Running Blocking Code" msgstr "執行阻塞的程式" #: ../../library/asyncio-dev.rst:123 msgid "" "Blocking (CPU-bound) code should not be called directly. For example, if a " "function performs a CPU-intensive calculation for 1 second, all concurrent " "asyncio Tasks and IO operations would be delayed by 1 second." msgstr "" "不應該直接呼叫阻塞(CPU 密集型)程式。例如一個執行 1 秒 CPU 密集型計算的函" "式,那麼所有並行非同步 Tasks 和 IO 操作都會被延遲 1 秒。" #: ../../library/asyncio-dev.rst:128 msgid "" "An executor can be used to run a task in a different thread, including in a " "different interpreter, or even in a different process to avoid blocking the " "OS thread with the event loop. See the :meth:`loop.run_in_executor` method " "for more details." msgstr "" "一個 executor(執行器)可以被用來在不同的執行緒(包含不同直譯器)、或甚至不同" "的行程中執行任務,以避免事件迴圈阻塞了 OS 執行緒。詳情請見 :meth:`loop." "run_in_executor` 方法。" #: ../../library/asyncio-dev.rst:138 msgid "Logging" msgstr "日誌記錄" #: ../../library/asyncio-dev.rst:140 msgid "" "asyncio uses the :mod:`logging` module and all logging is performed via the " "``\"asyncio\"`` logger." msgstr "" "asyncio 使用 :mod:`logging` 模組,所有日誌記錄都是透過 ``\"asyncio\"`` " "logger 執行的。" #: ../../library/asyncio-dev.rst:143 msgid "" "The default log level is :py:const:`logging.INFO`, which can be easily " "adjusted::" msgstr "日誌級別被預設為 :py:const:`logging.INFO`,它可以很容易地被調整: ::" #: ../../library/asyncio-dev.rst:146 msgid "logging.getLogger(\"asyncio\").setLevel(logging.WARNING)" msgstr "logging.getLogger(\"asyncio\").setLevel(logging.WARNING)" #: ../../library/asyncio-dev.rst:149 msgid "" "Network logging can block the event loop. It is recommended to use a " "separate thread for handling logs or use non-blocking IO. For example, see :" "ref:`blocking-handlers`." msgstr "" "網路日誌記錄可能會阻塞事件迴圈。建議使用獨立的執行緒來處理日誌或使用非阻塞 " "IO,範例請參見 :ref:`blocking-handlers`。" #: ../../library/asyncio-dev.rst:157 msgid "Detect never-awaited coroutines" msgstr "偵測從未被等待的 (never-awaited) 協程" #: ../../library/asyncio-dev.rst:159 msgid "" "When a coroutine function is called, but not awaited (e.g. ``coro()`` " "instead of ``await coro()``) or the coroutine is not scheduled with :meth:" "`asyncio.create_task`, asyncio will emit a :exc:`RuntimeWarning`::" msgstr "" "當協程函式被呼叫而不是被等待時(即執行 ``coro()`` 而不是 ``await coro()``)或" "者協程沒有透過 :meth:`asyncio.create_task` 被排程,asyncio 將會發出 :exc:" "`RuntimeWarning`: ::" #: ../../library/asyncio-dev.rst:164 msgid "" "import asyncio\n" "\n" "async def test():\n" " print(\"never scheduled\")\n" "\n" "async def main():\n" " test()\n" "\n" "asyncio.run(main())" msgstr "" "import asyncio\n" "\n" "async def test():\n" " print(\"never scheduled\")\n" "\n" "async def main():\n" " test()\n" "\n" "asyncio.run(main())" #: ../../library/asyncio-dev.rst:174 ../../library/asyncio-dev.rst:219 #: ../../library/asyncio-dev.rst:393 ../../library/asyncio-dev.rst:450 msgid "Output::" msgstr "輸出: ::" #: ../../library/asyncio-dev.rst:176 msgid "" "test.py:7: RuntimeWarning: coroutine 'test' was never awaited\n" " test()" msgstr "" "test.py:7: RuntimeWarning: coroutine 'test' was never awaited\n" " test()" #: ../../library/asyncio-dev.rst:179 ../../library/asyncio-dev.rst:235 msgid "Output in debug mode::" msgstr "除錯模式中的輸出: ::" #: ../../library/asyncio-dev.rst:181 msgid "" "test.py:7: RuntimeWarning: coroutine 'test' was never awaited\n" "Coroutine created at (most recent call last)\n" " File \"../t.py\", line 9, in \n" " asyncio.run(main(), debug=True)\n" "\n" " < .. >\n" "\n" " File \"../t.py\", line 7, in main\n" " test()\n" " test()" msgstr "" "test.py:7: RuntimeWarning: coroutine 'test' was never awaited\n" "Coroutine created at (most recent call last)\n" " File \"../t.py\", line 9, in \n" " asyncio.run(main(), debug=True)\n" "\n" " < .. >\n" "\n" " File \"../t.py\", line 7, in main\n" " test()\n" " test()" #: ../../library/asyncio-dev.rst:192 msgid "" "The usual fix is to either await the coroutine or call the :meth:`asyncio." "create_task` function::" msgstr "" "常用的修復方法是去等待協程或者呼叫 :meth:`asyncio.create_task` 函式: ::" #: ../../library/asyncio-dev.rst:195 msgid "" "async def main():\n" " await test()" msgstr "" "async def main():\n" " await test()" #: ../../library/asyncio-dev.rst:200 msgid "Detect never-retrieved exceptions" msgstr "偵測從未被取得的 (never-retrieved) 例外" #: ../../library/asyncio-dev.rst:202 msgid "" "If a :meth:`Future.set_exception` is called but the Future object is never " "awaited on, the exception would never be propagated to the user code. In " "this case, asyncio would emit a log message when the Future object is " "garbage collected." msgstr "" "如果呼叫 :meth:`Future.set_exception`,但 Future 物件從未被等待,例外將無法被" "傳播 (propagate) 到使用者程式。在這種情況下,當 Future 物件被垃圾回收 " "(garbage collected) 時,asyncio 將發出一則日誌訊息。" #: ../../library/asyncio-dev.rst:207 msgid "Example of an unhandled exception::" msgstr "未處理例外的例子: ::" #: ../../library/asyncio-dev.rst:209 msgid "" "import asyncio\n" "\n" "async def bug():\n" " raise Exception(\"not consumed\")\n" "\n" "async def main():\n" " asyncio.create_task(bug())\n" "\n" "asyncio.run(main())" msgstr "" "import asyncio\n" "\n" "async def bug():\n" " raise Exception(\"not consumed\")\n" "\n" "async def main():\n" " asyncio.create_task(bug())\n" "\n" "asyncio.run(main())" #: ../../library/asyncio-dev.rst:221 msgid "" "Task exception was never retrieved\n" "future: \n" " exception=Exception('not consumed')>\n" "\n" "Traceback (most recent call last):\n" " File \"test.py\", line 4, in bug\n" " raise Exception(\"not consumed\")\n" "Exception: not consumed" msgstr "" "Task exception was never retrieved\n" "future: \n" " exception=Exception('not consumed')>\n" "\n" "Traceback (most recent call last):\n" " File \"test.py\", line 4, in bug\n" " raise Exception(\"not consumed\")\n" "Exception: not consumed" #: ../../library/asyncio-dev.rst:230 msgid "" ":ref:`Enable the debug mode ` to get the traceback where " "the task was created::" msgstr "" ":ref:`啟用除錯模式 `\\ 以取得任務建立處的追蹤資訊 " "(traceback): ::" #: ../../library/asyncio-dev.rst:233 msgid "asyncio.run(main(), debug=True)" msgstr "asyncio.run(main(), debug=True)" #: ../../library/asyncio-dev.rst:237 msgid "" "Task exception was never retrieved\n" "future: \n" " exception=Exception('not consumed') created at asyncio/tasks.py:321>\n" "\n" "source_traceback: Object created at (most recent call last):\n" " File \"../t.py\", line 9, in \n" " asyncio.run(main(), debug=True)\n" "\n" "< .. >\n" "\n" "Traceback (most recent call last):\n" " File \"../t.py\", line 4, in bug\n" " raise Exception(\"not consumed\")\n" "Exception: not consumed" msgstr "" "Task exception was never retrieved\n" "future: \n" " exception=Exception('not consumed') created at asyncio/tasks.py:321>\n" "\n" "source_traceback: Object created at (most recent call last):\n" " File \"../t.py\", line 9, in \n" " asyncio.run(main(), debug=True)\n" "\n" "< .. >\n" "\n" "Traceback (most recent call last):\n" " File \"../t.py\", line 4, in bug\n" " raise Exception(\"not consumed\")\n" "Exception: not consumed" #: ../../library/asyncio-dev.rst:254 msgid "Asynchronous generators best practices" msgstr "" #: ../../library/asyncio-dev.rst:256 msgid "" "Writing correct and efficient asyncio code requires awareness of certain " "pitfalls. This section outlines essential best practices that can save you " "hours of debugging." msgstr "" #: ../../library/asyncio-dev.rst:261 msgid "Close asynchronous generators explicitly" msgstr "" #: ../../library/asyncio-dev.rst:263 msgid "" "It is recommended to manually close the :term:`asynchronous generator " "`. If a generator exits early - for " "example, due to an exception raised in the body of an ``async for`` loop - " "its asynchronous cleanup code may run in an unexpected context. This can " "occur after the tasks it depends on have completed, or during the event loop " "shutdown when the async-generator's garbage collection hook is called." msgstr "" #: ../../library/asyncio-dev.rst:271 msgid "" "To avoid this, explicitly close the generator by calling its :meth:`~agen." "aclose` method, or use the :func:`contextlib.aclosing` context manager::" msgstr "" #: ../../library/asyncio-dev.rst:275 msgid "" "import asyncio\n" "import contextlib\n" "\n" "async def gen():\n" " yield 1\n" " yield 2\n" "\n" "async def func():\n" " async with contextlib.aclosing(gen()) as g:\n" " async for x in g:\n" " break # Don't iterate until the end\n" "\n" "asyncio.run(func())" msgstr "" #: ../../library/asyncio-dev.rst:289 msgid "" "As noted above, the cleanup code for these asynchronous generators is " "deferred. The following example demonstrates that the finalization of an " "asynchronous generator can occur in an unexpected order::" msgstr "" #: ../../library/asyncio-dev.rst:293 msgid "" "import asyncio\n" "work_done = False\n" "\n" "async def cursor():\n" " try:\n" " yield 1\n" " finally:\n" " assert work_done\n" "\n" "async def rows():\n" " global work_done\n" " try:\n" " yield 2\n" " finally:\n" " await asyncio.sleep(0.1) # immitate some async work\n" " work_done = True\n" "\n" "\n" "async def main():\n" " async for c in cursor():\n" " async for r in rows():\n" " break\n" " break\n" "\n" "asyncio.run(main())" msgstr "" #: ../../library/asyncio-dev.rst:319 msgid "For this example, we get the following output::" msgstr "" #: ../../library/asyncio-dev.rst:321 msgid "" "unhandled exception during asyncio.run() shutdown\n" "task: ()> exception=AssertionError()>\n" "Traceback (most recent call last):\n" " File \"example.py\", line 6, in cursor\n" " yield 1\n" "asyncio.exceptions.CancelledError\n" "\n" "During handling of the above exception, another exception occurred:\n" "\n" "Traceback (most recent call last):\n" " File \"example.py\", line 8, in cursor\n" " assert work_done\n" " ^^^^^^^^^\n" "AssertionError" msgstr "" #: ../../library/asyncio-dev.rst:336 msgid "" "The ``cursor()`` asynchronous generator was finalized before the ``rows`` " "generator - an unexpected behavior." msgstr "" #: ../../library/asyncio-dev.rst:339 msgid "" "The example can be fixed by explicitly closing the ``cursor`` and ``rows`` " "async-generators::" msgstr "" #: ../../library/asyncio-dev.rst:342 msgid "" "async def main():\n" " async with contextlib.aclosing(cursor()) as cursor_gen:\n" " async for c in cursor_gen:\n" " async with contextlib.aclosing(rows()) as rows_gen:\n" " async for r in rows_gen:\n" " break\n" " break" msgstr "" #: ../../library/asyncio-dev.rst:352 msgid "Create asynchronous generators only when the event loop is running" msgstr "" #: ../../library/asyncio-dev.rst:354 msgid "" "It is recommended to create :term:`asynchronous generators ` only after the event loop has been created." msgstr "" #: ../../library/asyncio-dev.rst:358 msgid "" "To ensure that asynchronous generators close reliably, the event loop uses " "the :func:`sys.set_asyncgen_hooks` function to register callback functions. " "These callbacks update the list of running asynchronous generators to keep " "it in a consistent state." msgstr "" #: ../../library/asyncio-dev.rst:363 msgid "" "When the :meth:`loop.shutdown_asyncgens() ` " "function is called, the running generators are stopped gracefully and the " "list is cleared." msgstr "" #: ../../library/asyncio-dev.rst:367 msgid "" "The asynchronous generator invokes the corresponding system hook during its " "first iteration. At the same time, the generator records that the hook has " "been called and does not call it again." msgstr "" #: ../../library/asyncio-dev.rst:371 msgid "" "Therefore, if iteration begins before the event loop is created, the event " "loop will not be able to add the generator to its list of active generators " "because the hooks are set after the generator attempts to call them. " "Consequently, the event loop will not be able to terminate the generator if " "necessary." msgstr "" #: ../../library/asyncio-dev.rst:377 msgid "Consider the following example::" msgstr "" #: ../../library/asyncio-dev.rst:379 msgid "" "import asyncio\n" "\n" "async def agenfn():\n" " try:\n" " yield 10\n" " finally:\n" " await asyncio.sleep(0)\n" "\n" "\n" "with asyncio.Runner() as runner:\n" " agen = agenfn()\n" " print(runner.run(anext(agen)))\n" " del agen" msgstr "" #: ../../library/asyncio-dev.rst:395 msgid "" "10\n" "Exception ignored while closing generator :\n" "Traceback (most recent call last):\n" " File \"example.py\", line 13, in \n" " del agen\n" " ^^^^\n" "RuntimeError: async generator ignored GeneratorExit" msgstr "" #: ../../library/asyncio-dev.rst:403 msgid "This example can be fixed as follows::" msgstr "" #: ../../library/asyncio-dev.rst:405 msgid "" "import asyncio\n" "\n" "async def agenfn():\n" " try:\n" " yield 10\n" " finally:\n" " await asyncio.sleep(0)\n" "\n" "async def main():\n" " agen = agenfn()\n" " print(await anext(agen))\n" " del agen\n" "\n" "asyncio.run(main())" msgstr "" "import asyncio\n" "\n" "async def agenfn():\n" " try:\n" " yield 10\n" " finally:\n" " await asyncio.sleep(0)\n" "\n" "async def main():\n" " agen = agenfn()\n" " print(await anext(agen))\n" " del agen\n" "\n" "asyncio.run(main())" #: ../../library/asyncio-dev.rst:422 msgid "Avoid concurrent iteration and closure of the same generator" msgstr "" #: ../../library/asyncio-dev.rst:424 msgid "" "Async generators may be reentered while another :meth:`~agen.__anext__` / :" "meth:`~agen.athrow` / :meth:`~agen.aclose` call is in progress. This may " "lead to an inconsistent state of the async generator and can cause errors." msgstr "" #: ../../library/asyncio-dev.rst:429 msgid "Let's consider the following example::" msgstr "" #: ../../library/asyncio-dev.rst:431 msgid "" "import asyncio\n" "\n" "async def consumer():\n" " for idx in range(100):\n" " await asyncio.sleep(0)\n" " message = yield idx\n" " print('received', message)\n" "\n" "async def amain():\n" " agenerator = consumer()\n" " await agenerator.asend(None)\n" "\n" " fa = asyncio.create_task(agenerator.asend('A'))\n" " fb = asyncio.create_task(agenerator.asend('B'))\n" " await fa\n" " await fb\n" "\n" "asyncio.run(amain())" msgstr "" #: ../../library/asyncio-dev.rst:452 msgid "" "received A\n" "Traceback (most recent call last):\n" " File \"test.py\", line 38, in \n" " asyncio.run(amain())\n" " ~~~~~~~~~~~^^^^^^^^^\n" " File \"Lib/asyncio/runners.py\", line 204, in run\n" " return runner.run(main)\n" " ~~~~~~~~~~^^^^^^\n" " File \"Lib/asyncio/runners.py\", line 127, in run\n" " return self._loop.run_until_complete(task)\n" " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^\n" " File \"Lib/asyncio/base_events.py\", line 719, in run_until_complete\n" " return future.result()\n" " ~~~~~~~~~~~~~^^\n" " File \"test.py\", line 36, in amain\n" " await fb\n" "RuntimeError: anext(): asynchronous generator is already running" msgstr "" #: ../../library/asyncio-dev.rst:471 msgid "" "Therefore, it is recommended to avoid using asynchronous generators in " "parallel tasks or across multiple event loops." msgstr ""