|
| 1 | +# SOME DESCRIPTIVE TITLE. |
| 2 | +# Copyright (C) 2001 Python Software Foundation |
| 3 | +# This file is distributed under the same license as the Python package. |
| 4 | +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. |
| 5 | +# |
| 6 | +#, fuzzy |
| 7 | +msgid "" |
| 8 | +msgstr "" |
| 9 | +"Project-Id-Version: Python 3.14\n" |
| 10 | +"Report-Msgid-Bugs-To: \n" |
| 11 | +"POT-Creation-Date: 2026-06-11 00:43+0000\n" |
| 12 | +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
| 13 | +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
| 14 | +"Language-Team: LANGUAGE <LL@li.org>\n" |
| 15 | +"Language: zh_TW\n" |
| 16 | +"MIME-Version: 1.0\n" |
| 17 | +"Content-Type: text/plain; charset=UTF-8\n" |
| 18 | +"Content-Transfer-Encoding: 8bit\n" |
| 19 | + |
| 20 | +#: ../../library/asyncio-threading.rst:6 |
| 21 | +msgid "asyncio and free-threaded Python" |
| 22 | +msgstr "" |
| 23 | + |
| 24 | +#: ../../library/asyncio-threading.rst:8 |
| 25 | +msgid "" |
| 26 | +"asyncio uses an event loop as a scheduler to enable highly efficient " |
| 27 | +"concurrency by switching between tasks to allow non-blocking I/O operations. " |
| 28 | +"This results in better performance for I/O-bound use cases. It also allows " |
| 29 | +"off-loading CPU-bound work to a thread or process pool, but that is still " |
| 30 | +"limited by the :term:`global interpreter lock` in CPython." |
| 31 | +msgstr "" |
| 32 | + |
| 33 | +#: ../../library/asyncio-threading.rst:15 |
| 34 | +msgid "" |
| 35 | +"However, in :ref:`free-threaded Python <freethreading-python-howto>`, the " |
| 36 | +"GIL is disabled and Python can run true multi-threaded code. This means that " |
| 37 | +"asyncio can now take advantage of multiple CPU cores without the limitations " |
| 38 | +"imposed by the GIL." |
| 39 | +msgstr "" |
| 40 | + |
| 41 | +#: ../../library/asyncio-threading.rst:20 |
| 42 | +msgid "" |
| 43 | +"Since Python 3.14, asyncio has first-class support for free-threaded Python, " |
| 44 | +"and the implementation of asyncio is safe to use in a multi-threaded " |
| 45 | +"environment." |
| 46 | +msgstr "" |
| 47 | + |
| 48 | +#: ../../library/asyncio-threading.rst:24 |
| 49 | +msgid "" |
| 50 | +"A single event loop on one core can handle many connections concurrently, " |
| 51 | +"but the Python code that runs to handle each one still executes serially. " |
| 52 | +"Once requests involve a non-trivial amount of per-request computation, that " |
| 53 | +"handling becomes the bottleneck, and a single core can no longer keep up. " |
| 54 | +"Combining asyncio with threads is most useful here: by running an event loop " |
| 55 | +"per thread, the handling of different requests can run in parallel across " |
| 56 | +"multiple CPU cores. It is also useful when you need to run blocking or CPU-" |
| 57 | +"bound code from an asyncio application." |
| 58 | +msgstr "" |
| 59 | + |
| 60 | +#: ../../library/asyncio-threading.rst:37 |
| 61 | +msgid "" |
| 62 | +"`Scaling asyncio on Free-Threaded Python <https://labs.quansight.org/blog/" |
| 63 | +"scaling-asyncio-on-free-threaded-python>`__, a blog post by Kumar Aditya " |
| 64 | +"which explains the internal changes that make asyncio safe and efficient " |
| 65 | +"under free-threaded Python, together with benchmarks of the resulting " |
| 66 | +"improvements." |
| 67 | +msgstr "" |
| 68 | + |
| 69 | +#: ../../library/asyncio-threading.rst:45 |
| 70 | +msgid "Thread safety considerations" |
| 71 | +msgstr "" |
| 72 | + |
| 73 | +#: ../../library/asyncio-threading.rst:47 |
| 74 | +msgid "" |
| 75 | +"While asyncio is designed to be thread-safe in a free-threaded Python " |
| 76 | +"environment, there are still some considerations to keep in mind when using " |
| 77 | +"asyncio with threads:" |
| 78 | +msgstr "" |
| 79 | + |
| 80 | +#: ../../library/asyncio-threading.rst:51 |
| 81 | +msgid "" |
| 82 | +"**Event loop**: Each thread should have its own event loop which should not " |
| 83 | +"be shared across threads. This ensures that the event loop can manage its " |
| 84 | +"own tasks and callbacks without interference from other threads." |
| 85 | +msgstr "" |
| 86 | + |
| 87 | +#: ../../library/asyncio-threading.rst:56 |
| 88 | +msgid "" |
| 89 | +"**Task management**: Tasks and futures created in one thread should not be " |
| 90 | +"awaited or manipulated from another thread." |
| 91 | +msgstr "" |
| 92 | + |
| 93 | +#: ../../library/asyncio-threading.rst:59 |
| 94 | +msgid "" |
| 95 | +"**Thread-safe APIs**: When interacting with asyncio from multiple threads, " |
| 96 | +"it's important to use thread-safe APIs provided by asyncio, such as :func:" |
| 97 | +"`asyncio.run_coroutine_threadsafe` for submitting coroutines to an event " |
| 98 | +"loop from another thread. If you need to call a callback from a different " |
| 99 | +"thread, you can use :meth:`loop.call_soon_threadsafe` to schedule it safely." |
| 100 | +msgstr "" |
| 101 | + |
| 102 | +#: ../../library/asyncio-threading.rst:66 |
| 103 | +msgid "" |
| 104 | +"**Synchronization**: The synchronization primitives provided by asyncio " |
| 105 | +"(like :class:`asyncio.Lock` and :class:`asyncio.Event`) are not designed to " |
| 106 | +"be used across threads. If you need to synchronize between threads, you " |
| 107 | +"should use the synchronization primitives from the :mod:`threading` module " |
| 108 | +"instead." |
| 109 | +msgstr "" |
| 110 | + |
| 111 | +#: ../../library/asyncio-threading.rst:74 |
| 112 | +msgid "Using asyncio with threads" |
| 113 | +msgstr "" |
| 114 | + |
| 115 | +#: ../../library/asyncio-threading.rst:76 |
| 116 | +msgid "" |
| 117 | +"asyncio supports running one event loop per thread, which allows you to take " |
| 118 | +"advantage of multiple CPU cores in a free-threaded Python environment. Each " |
| 119 | +"thread can run its own event loop, and tasks can be scheduled on those loops " |
| 120 | +"independently." |
| 121 | +msgstr "" |
| 122 | + |
| 123 | +#: ../../library/asyncio-threading.rst:81 |
| 124 | +msgid "Here's an example of how to use asyncio with threads::" |
| 125 | +msgstr "" |
| 126 | + |
| 127 | +#: ../../library/asyncio-threading.rst:83 |
| 128 | +msgid "" |
| 129 | +"import asyncio\n" |
| 130 | +"import threading\n" |
| 131 | +"\n" |
| 132 | +"async def worker(name: str) -> None:\n" |
| 133 | +" print(f\"Worker {name} starting\")\n" |
| 134 | +" await asyncio.sleep(1)\n" |
| 135 | +" print(f\"Worker {name} done\")\n" |
| 136 | +"\n" |
| 137 | +"def run_loop(name: str) -> None:\n" |
| 138 | +" asyncio.run(worker(name))\n" |
| 139 | +"\n" |
| 140 | +"threads = [\n" |
| 141 | +" threading.Thread(target=run_loop, args=(f\"T{i}\",))\n" |
| 142 | +" for i in range(4)\n" |
| 143 | +"]\n" |
| 144 | +"for t in threads:\n" |
| 145 | +" t.start()\n" |
| 146 | +"for t in threads:\n" |
| 147 | +" t.join()" |
| 148 | +msgstr "" |
| 149 | + |
| 150 | +#: ../../library/asyncio-threading.rst:103 |
| 151 | +msgid "" |
| 152 | +"In this example, each thread creates its own event loop with :func:`asyncio." |
| 153 | +"run` and runs a coroutine on it. The threads execute concurrently, and in a " |
| 154 | +"free-threaded build they can run on separate CPU cores in parallel." |
| 155 | +msgstr "" |
| 156 | + |
| 157 | +#: ../../library/asyncio-threading.rst:110 |
| 158 | +msgid "Producer/consumer across threads" |
| 159 | +msgstr "" |
| 160 | + |
| 161 | +#: ../../library/asyncio-threading.rst:112 |
| 162 | +msgid "" |
| 163 | +"When a regular (non-asyncio) thread needs to hand work to an asyncio event " |
| 164 | +"loop running in another thread, use a thread-safe primitive such as :class:" |
| 165 | +"`queue.Queue` rather than :class:`asyncio.Queue`, which is only safe within " |
| 166 | +"a single event loop.::" |
| 167 | +msgstr "" |
| 168 | + |
| 169 | +#: ../../library/asyncio-threading.rst:117 |
| 170 | +msgid "" |
| 171 | +"import asyncio\n" |
| 172 | +"import queue\n" |
| 173 | +"import threading\n" |
| 174 | +"\n" |
| 175 | +"def producer(q: queue.Queue[int]) -> None:\n" |
| 176 | +" for i in range(5):\n" |
| 177 | +" print(f\"Producing {i}\")\n" |
| 178 | +" q.put(i)\n" |
| 179 | +" q.shutdown()\n" |
| 180 | +"\n" |
| 181 | +"async def consumer(q: queue.Queue[int]) -> None:\n" |
| 182 | +" while True:\n" |
| 183 | +" try:\n" |
| 184 | +" item = q.get_nowait()\n" |
| 185 | +" except queue.Empty:\n" |
| 186 | +" await asyncio.sleep(0.1)\n" |
| 187 | +" continue\n" |
| 188 | +" except queue.ShutDown:\n" |
| 189 | +" break\n" |
| 190 | +" print(f\"Consumed {item}\")\n" |
| 191 | +" await asyncio.sleep(item)\n" |
| 192 | +"\n" |
| 193 | +"q: queue.Queue[int] = queue.Queue()\n" |
| 194 | +"consumer_thread = threading.Thread(\n" |
| 195 | +" target=lambda: asyncio.run(consumer(q))\n" |
| 196 | +")\n" |
| 197 | +"consumer_thread.start()\n" |
| 198 | +"producer(q)\n" |
| 199 | +"consumer_thread.join()" |
| 200 | +msgstr "" |
| 201 | + |
| 202 | +#: ../../library/asyncio-threading.rst:147 |
| 203 | +msgid "" |
| 204 | +"The producer runs on the main thread while the consumer runs inside an event " |
| 205 | +"loop on its own thread, yet they communicate safely through ``queue.Queue``. " |
| 206 | +"When the queue is empty the consumer sleeps briefly and tries again. When " |
| 207 | +"the producer is done it calls :meth:`~queue.Queue.shutdown`, which causes " |
| 208 | +"subsequent :meth:`~queue.Queue.get_nowait` calls to raise :exc:`queue." |
| 209 | +"ShutDown` so the consumer can exit cleanly." |
| 210 | +msgstr "" |
0 commit comments