Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
02a0a192
Commit
02a0a192
authored
Dec 14, 2017
by
Yury Selivanov
Committed by
GitHub
Dec 14, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bpo-32314: Implement asyncio.run() (#4852)
parent
eadad1b9
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
173 additions
and
9 deletions
+173
-9
Doc/library/asyncio-task.rst
Doc/library/asyncio-task.rst
+22
-9
Lib/asyncio/__init__.py
Lib/asyncio/__init__.py
+2
-0
Lib/asyncio/runners.py
Lib/asyncio/runners.py
+48
-0
Lib/test/test_asyncio/test_runners.py
Lib/test/test_asyncio/test_runners.py
+100
-0
Misc/NEWS.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst
...S.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst
+1
-0
No files found.
Doc/library/asyncio-task.rst
View file @
02a0a192
...
...
@@ -92,6 +92,24 @@ Coroutines (and tasks) can only run when the event loop is running.
used in a callback-style code, wrap its result with :func:`ensure_future`.
.. function:: asyncio.run(coro, \*, debug=False)
This function runs the passed coroutine, taking care of
managing the asyncio event loop and finalizing asynchronous
generators.
This function cannot be called when another asyncio event loop is
running in the same thread.
If debug is True, the event loop will be run in debug mode.
This function always creates a new event loop and closes it at
the end. It should be used as a main entry point for asyncio
programs, and should ideally only be called once.
.. versionadded:: 3.7
.. _asyncio-hello-world-coroutine:
Example: Hello World coroutine
...
...
@@ -104,10 +122,7 @@ Example of coroutine displaying ``"Hello World"``::
async def hello_world():
print("Hello World!")
loop = asyncio.get_event_loop()
# Blocking call which returns when the hello_world() coroutine is done
loop.run_until_complete(hello_world())
loop.close()
asyncio.run(hello_world())
.. seealso::
...
...
@@ -127,7 +142,8 @@ using the :meth:`sleep` function::
import asyncio
import datetime
async def display_date(loop):
async def display_date():
loop = asyncio.get_running_loop()
end_time = loop.time() + 5.0
while True:
print(datetime.datetime.now())
...
...
@@ -135,10 +151,7 @@ using the :meth:`sleep` function::
break
await asyncio.sleep(1)
loop = asyncio.get_event_loop()
# Blocking call which returns when the display_date() coroutine is done
loop.run_until_complete(display_date(loop))
loop.close()
asyncio.run(display_date())
.. seealso::
...
...
Lib/asyncio/__init__.py
View file @
02a0a192
...
...
@@ -11,6 +11,7 @@ from .events import *
from
.futures
import
*
from
.locks
import
*
from
.protocols
import
*
from
.runners
import
*
from
.queues
import
*
from
.streams
import
*
from
.subprocess
import
*
...
...
@@ -23,6 +24,7 @@ __all__ = (base_events.__all__ +
futures
.
__all__
+
locks
.
__all__
+
protocols
.
__all__
+
runners
.
__all__
+
queues
.
__all__
+
streams
.
__all__
+
subprocess
.
__all__
+
...
...
Lib/asyncio/runners.py
0 → 100644
View file @
02a0a192
__all__
=
'run'
,
from
.
import
coroutines
from
.
import
events
def
run
(
main
,
*
,
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 cannot be called when another asyncio event loop is
running in the same thread.
If debug is True, the event loop will be run in debug mode.
This function always creates a new event loop and closes it at the end.
It should be used as a main entry point for asyncio programs, and should
ideally only be called once.
Example:
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
coroutines
.
iscoroutine
(
main
):
raise
ValueError
(
"a coroutine was expected, got {!r}"
.
format
(
main
))
loop
=
events
.
new_event_loop
()
try
:
events
.
set_event_loop
(
loop
)
loop
.
set_debug
(
debug
)
return
loop
.
run_until_complete
(
main
)
finally
:
try
:
loop
.
run_until_complete
(
loop
.
shutdown_asyncgens
())
finally
:
events
.
set_event_loop
(
None
)
loop
.
close
()
Lib/test/test_asyncio/test_runners.py
0 → 100644
View file @
02a0a192
import
asyncio
import
unittest
from
unittest
import
mock
class
TestPolicy
(
asyncio
.
AbstractEventLoopPolicy
):
def
__init__
(
self
,
loop_factory
):
self
.
loop_factory
=
loop_factory
self
.
loop
=
None
def
get_event_loop
(
self
):
# shouldn't ever be called by asyncio.run()
raise
RuntimeError
def
new_event_loop
(
self
):
return
self
.
loop_factory
()
def
set_event_loop
(
self
,
loop
):
if
loop
is
not
None
:
# we want to check if the loop is closed
# in BaseTest.tearDown
self
.
loop
=
loop
class
BaseTest
(
unittest
.
TestCase
):
def
new_loop
(
self
):
loop
=
asyncio
.
BaseEventLoop
()
loop
.
_process_events
=
mock
.
Mock
()
loop
.
_selector
=
mock
.
Mock
()
loop
.
_selector
.
select
.
return_value
=
()
loop
.
shutdown_ag_run
=
False
async
def
shutdown_asyncgens
():
loop
.
shutdown_ag_run
=
True
loop
.
shutdown_asyncgens
=
shutdown_asyncgens
return
loop
def
setUp
(
self
):
super
().
setUp
()
policy
=
TestPolicy
(
self
.
new_loop
)
asyncio
.
set_event_loop_policy
(
policy
)
def
tearDown
(
self
):
policy
=
asyncio
.
get_event_loop_policy
()
if
policy
.
loop
is
not
None
:
self
.
assertTrue
(
policy
.
loop
.
is_closed
())
self
.
assertTrue
(
policy
.
loop
.
shutdown_ag_run
)
asyncio
.
set_event_loop_policy
(
None
)
super
().
tearDown
()
class
RunTests
(
BaseTest
):
def
test_asyncio_run_return
(
self
):
async
def
main
():
await
asyncio
.
sleep
(
0
)
return
42
self
.
assertEqual
(
asyncio
.
run
(
main
()),
42
)
def
test_asyncio_run_raises
(
self
):
async
def
main
():
await
asyncio
.
sleep
(
0
)
raise
ValueError
(
'spam'
)
with
self
.
assertRaisesRegex
(
ValueError
,
'spam'
):
asyncio
.
run
(
main
())
def
test_asyncio_run_only_coro
(
self
):
for
o
in
{
1
,
lambda
:
None
}:
with
self
.
subTest
(
obj
=
o
),
\
self
.
assertRaisesRegex
(
ValueError
,
'a coroutine was expected'
):
asyncio
.
run
(
o
)
def
test_asyncio_run_debug
(
self
):
async
def
main
(
expected
):
loop
=
asyncio
.
get_event_loop
()
self
.
assertIs
(
loop
.
get_debug
(),
expected
)
asyncio
.
run
(
main
(
False
))
asyncio
.
run
(
main
(
True
),
debug
=
True
)
def
test_asyncio_run_from_running_loop
(
self
):
async
def
main
():
coro
=
main
()
try
:
asyncio
.
run
(
coro
)
finally
:
coro
.
close
()
# Suppress ResourceWarning
with
self
.
assertRaisesRegex
(
RuntimeError
,
'cannot be called from a running'
):
asyncio
.
run
(
main
())
Misc/NEWS.d/next/Library/2017-12-13-16-47-38.bpo-32314.W4_U2j.rst
0 → 100644
View file @
02a0a192
Implement asyncio.run().
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment