summaryrefslogtreecommitdiffstats
path: root/Doc/library
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/library')
-rw-r--r--Doc/library/asyncio-api-index.rst3
-rw-r--r--Doc/library/asyncio-task.rst56
2 files changed, 59 insertions, 0 deletions
diff --git a/Doc/library/asyncio-api-index.rst b/Doc/library/asyncio-api-index.rst
index d5b5659..047e5bb 100644
--- a/Doc/library/asyncio-api-index.rst
+++ b/Doc/library/asyncio-api-index.rst
@@ -48,6 +48,9 @@ await on multiple things with timeouts.
* - :class:`Task`
- Task object.
+ * - :func:`to_thread`
+ - Asychronously run a function in a separate OS thread.
+
* - :func:`run_coroutine_threadsafe`
- Schedule a coroutine from another OS thread.
diff --git a/Doc/library/asyncio-task.rst b/Doc/library/asyncio-task.rst
index 2e96339..7c27040 100644
--- a/Doc/library/asyncio-task.rst
+++ b/Doc/library/asyncio-task.rst
@@ -602,6 +602,62 @@ Waiting Primitives
# ...
+Running in Threads
+==================
+
+.. coroutinefunction:: to_thread(func, /, \*args, \*\*kwargs)
+
+ Asynchronously run function *func* in a separate thread.
+
+ Any \*args and \*\*kwargs supplied for this function are directly passed
+ to *func*.
+
+ Return an :class:`asyncio.Future` which represents the eventual result of
+ *func*.
+
+ This coroutine function is primarily intended to be used for executing
+ IO-bound functions/methods that would otherwise block the event loop if
+ they were ran in the main thread. For example::
+
+ def blocking_io():
+ print(f"start blocking_io at {time.strftime('%X')}")
+ # Note that time.sleep() can be replaced with any blocking
+ # IO-bound operation, such as file operations.
+ time.sleep(1)
+ print(f"blocking_io complete at {time.strftime('%X')}")
+
+ async def main():
+ print(f"started main at {time.strftime('%X')}")
+
+ await asyncio.gather(
+ asyncio.to_thread(blocking_io),
+ asyncio.sleep(1))
+
+ print(f"finished main at {time.strftime('%X')}")
+
+
+ asyncio.run(main())
+
+ # Expected output:
+ #
+ # started main at 19:50:53
+ # start blocking_io at 19:50:53
+ # blocking_io complete at 19:50:54
+ # finished main at 19:50:54
+
+ Directly calling `blocking_io()` in any coroutine would block the event loop
+ for its duration, resulting in an additional 1 second of run time. Instead,
+ by using `asyncio.to_thread()`, we can run it in a separate thread without
+ blocking the event loop.
+
+ .. note::
+
+ Due to the :term:`GIL`, `asyncio.to_thread()` can typically only be used
+ to make IO-bound functions non-blocking. However, for extension modules
+ that release the GIL or alternative Python implementations that don't
+ have one, `asyncio.to_thread()` can also be used for CPU-bound functions.
+
+
Scheduling From Other Threads
=============================