]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
expand the `asyncio.run_coroutine_threadsafe` recipes (#127576)
authorThomas Grainger <tagrain@gmail.com>
Sun, 29 Dec 2024 06:22:29 +0000 (06:22 +0000)
committerGitHub <noreply@github.com>
Sun, 29 Dec 2024 06:22:29 +0000 (11:52 +0530)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Doc/library/asyncio-task.rst

index f27e858cf420f4bf3a925abcc3e96c01042e522c..4541cf28de0605dd4f233d2836b7116207d89c8d 100644 (file)
@@ -1067,14 +1067,59 @@ Scheduling From Other Threads
    This function is meant to be called from a different OS thread
    than the one where the event loop is running.  Example::
 
-     # Create a coroutine
-     coro = asyncio.sleep(1, result=3)
-
-     # Submit the coroutine to a given loop
-     future = asyncio.run_coroutine_threadsafe(coro, loop)
-
-     # Wait for the result with an optional timeout argument
-     assert future.result(timeout) == 3
+     def in_thread(loop: asyncio.AbstractEventLoop) -> None:
+         # Run some blocking IO
+         pathlib.Path("example.txt").write_text("hello world", encoding="utf8")
+
+         # Create a coroutine
+         coro = asyncio.sleep(1, result=3)
+
+         # Submit the coroutine to a given loop
+         future = asyncio.run_coroutine_threadsafe(coro, loop)
+
+         # Wait for the result with an optional timeout argument
+         assert future.result(timeout=2) == 3
+
+     async def amain() -> None:
+         # Get the running loop
+         loop = asyncio.get_running_loop()
+
+         # Run something in a thread
+         await asyncio.to_thread(in_thread, loop)
+
+   It's also possible to run the other way around.  Example::
+
+     @contextlib.contextmanager
+     def loop_in_thread() -> Generator[asyncio.AbstractEventLoop]:
+         loop_fut = concurrent.futures.Future[asyncio.AbstractEventLoop]()
+         stop_event = asyncio.Event()
+
+         async def main() -> None:
+             loop_fut.set_result(asyncio.get_running_loop())
+             await stop_event.wait()
+
+         with concurrent.futures.ThreadPoolExecutor(1) as tpe:
+             complete_fut = tpe.submit(asyncio.run, main())
+             for fut in concurrent.futures.as_completed((loop_fut, complete_fut)):
+                 if fut is loop_fut:
+                     loop = loop_fut.result()
+                     try:
+                         yield loop
+                     finally:
+                         loop.call_soon_threadsafe(stop_event.set)
+                 else:
+                     fut.result()
+
+     # Create a loop in another thread
+     with loop_in_thread() as loop:
+         # Create a coroutine
+         coro = asyncio.sleep(1, result=3)
+
+         # Submit the coroutine to a given loop
+         future = asyncio.run_coroutine_threadsafe(coro, loop)
+
+         # Wait for the result with an optional timeout argument
+         assert future.result(timeout=2) == 3
 
    If an exception is raised in the coroutine, the returned Future
    will be notified.  It can also be used to cancel the task in