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

Commit

Permalink
Add asyncio.run() and asyncio.run_in_executor() functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
1st1 committed Nov 10, 2016
1 parent eb4c3ff commit db2fe1d
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 1 deletion.
1 change: 1 addition & 0 deletions asyncio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from .futures import *
from .locks import *
from .protocols import *
from .run import *
from .queues import *
from .streams import *
from .subprocess import *
Expand Down
23 changes: 22 additions & 1 deletion asyncio/base_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from .log import logger


__all__ = ['BaseEventLoop']
__all__ = ['BaseEventLoop', 'run_in_executor']


# Minimum number of _scheduled timer handles before cleanup of
Expand All @@ -55,6 +55,27 @@
ConnectionResetError, ConnectionAbortedError)


@coroutine
def run_in_executor(executor, func, *args):
"""Run the function in a thread or a process pool.
Any concurrent.futures executor can be passed to the
function.
If executor is None, the function will be run in
the default threadpool of the event loop.
Example:
async def coro():
await asyncio.run_in_executor(
None, long_calculation, 42)
"""
loop = events.get_event_loop()
result = yield from loop.run_in_executor(executor, func, *args)
return result


def _format_handle(handle):
cb = handle._callback
if inspect.ismethod(cb) and isinstance(cb.__self__, tasks.Task):
Expand Down
68 changes: 68 additions & 0 deletions asyncio/run.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""asyncio.run() function."""

__all__ = ['run']

import threading

from . import coroutines
from . import events


def run(coro, *, debug=False):
"""Run a coroutine.
This function runs the passed coroutine, taking care of
managing the asyncio event loop and finalizing asynchronous
generators.
This function must be called from the main thread, and it
cannot be called when another asyncio event loop is running.
If debug is True, the event loop will be run in debug mode.
This function should be used as a main entry point for
asyncio programs, and should not be used to call asynchronous
APIs.
Example::
import asyncio
async def main():
await asyncio.sleep(1)
print('hello')
asyncio.run(main())
"""
if events._get_running_loop() is not None:
raise RuntimeError(
"asyncio.run() cannot be called from a running event loop")
if not isinstance(threading.current_thread(), threading._MainThread):
raise RuntimeError(
"asyncio.run() must be called from the main thread")
if not coroutines.iscoroutine(coro):
raise ValueError("a coroutine was expected, got {!r}".format(coro))

loop = events.new_event_loop()
try:
events.set_event_loop(loop)

if debug:
loop.set_debug(True)

result = loop.run_until_complete(coro)

try:
# `shutdown_asyncgens` was added in Python 3.6; not all
# event loops might support it.
shutdown_asyncgens = loop.shutdown_asyncgens
except AttributeError:
pass
else:
loop.run_until_complete(shutdown_asyncgens())

return result

finally:
events.set_event_loop(None)
loop.close()

0 comments on commit db2fe1d

Please sign in to comment.