Skip to content
This repository was archived by the owner on Nov 23, 2017. It is now read-only.

Commit db2fe1d

Browse files
committed
Add asyncio.run() and asyncio.run_in_executor() functions.
1 parent eb4c3ff commit db2fe1d

File tree

3 files changed

+91
-1
lines changed

3 files changed

+91
-1
lines changed

asyncio/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from .futures import *
2525
from .locks import *
2626
from .protocols import *
27+
from .run import *
2728
from .queues import *
2829
from .streams import *
2930
from .subprocess import *

asyncio/base_events.py

+22-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
from .log import logger
3939

4040

41-
__all__ = ['BaseEventLoop']
41+
__all__ = ['BaseEventLoop', 'run_in_executor']
4242

4343

4444
# Minimum number of _scheduled timer handles before cleanup of
@@ -55,6 +55,27 @@
5555
ConnectionResetError, ConnectionAbortedError)
5656

5757

58+
@coroutine
59+
def run_in_executor(executor, func, *args):
60+
"""Run the function in a thread or a process pool.
61+
62+
Any concurrent.futures executor can be passed to the
63+
function.
64+
65+
If executor is None, the function will be run in
66+
the default threadpool of the event loop.
67+
68+
Example:
69+
70+
async def coro():
71+
await asyncio.run_in_executor(
72+
None, long_calculation, 42)
73+
"""
74+
loop = events.get_event_loop()
75+
result = yield from loop.run_in_executor(executor, func, *args)
76+
return result
77+
78+
5879
def _format_handle(handle):
5980
cb = handle._callback
6081
if inspect.ismethod(cb) and isinstance(cb.__self__, tasks.Task):

asyncio/run.py

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
"""asyncio.run() function."""
2+
3+
__all__ = ['run']
4+
5+
import threading
6+
7+
from . import coroutines
8+
from . import events
9+
10+
11+
def run(coro, *, debug=False):
12+
"""Run a coroutine.
13+
14+
This function runs the passed coroutine, taking care of
15+
managing the asyncio event loop and finalizing asynchronous
16+
generators.
17+
18+
This function must be called from the main thread, and it
19+
cannot be called when another asyncio event loop is running.
20+
21+
If debug is True, the event loop will be run in debug mode.
22+
23+
This function should be used as a main entry point for
24+
asyncio programs, and should not be used to call asynchronous
25+
APIs.
26+
27+
Example::
28+
29+
import asyncio
30+
31+
async def main():
32+
await asyncio.sleep(1)
33+
print('hello')
34+
35+
asyncio.run(main())
36+
"""
37+
if events._get_running_loop() is not None:
38+
raise RuntimeError(
39+
"asyncio.run() cannot be called from a running event loop")
40+
if not isinstance(threading.current_thread(), threading._MainThread):
41+
raise RuntimeError(
42+
"asyncio.run() must be called from the main thread")
43+
if not coroutines.iscoroutine(coro):
44+
raise ValueError("a coroutine was expected, got {!r}".format(coro))
45+
46+
loop = events.new_event_loop()
47+
try:
48+
events.set_event_loop(loop)
49+
50+
if debug:
51+
loop.set_debug(True)
52+
53+
result = loop.run_until_complete(coro)
54+
55+
try:
56+
# `shutdown_asyncgens` was added in Python 3.6; not all
57+
# event loops might support it.
58+
shutdown_asyncgens = loop.shutdown_asyncgens
59+
except AttributeError:
60+
pass
61+
else:
62+
loop.run_until_complete(shutdown_asyncgens())
63+
64+
return result
65+
66+
finally:
67+
events.set_event_loop(None)
68+
loop.close()

0 commit comments

Comments
 (0)