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

Commit 9acdceb

Browse files
committed
Add asyncio.forever()
1 parent db2fe1d commit 9acdceb

File tree

5 files changed

+57
-4
lines changed

5 files changed

+57
-4
lines changed

asyncio/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
streams.__all__ +
4242
subprocess.__all__ +
4343
tasks.__all__ +
44-
transports.__all__)
44+
transports.__all__ +
45+
['run', 'forever']) # Will fix this later.
4546

4647
if sys.platform == 'win32': # pragma: no cover
4748
from .windows_events import *

asyncio/base_events.py

+14
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,9 @@ def __init__(self):
294294
# Set to True when `loop.shutdown_asyncgens` is called.
295295
self._asyncgens_shutdown_called = False
296296

297+
# Future that isn't resolved while the loop is running.
298+
self._forever_fut = None
299+
297300
def __repr__(self):
298301
return ('<%s running=%s closed=%s debug=%s>'
299302
% (self.__class__.__name__, self.is_running(),
@@ -430,8 +433,12 @@ def shutdown_asyncgens(self):
430433
'asyncgen': agen
431434
})
432435

436+
def get_forever_future(self):
437+
return self._forever_fut
438+
433439
def run_forever(self):
434440
"""Run until stop() is called."""
441+
self._forever_fut = self.create_future()
435442
self._check_closed()
436443
if self.is_running():
437444
raise RuntimeError('This event loop is already running')
@@ -450,7 +457,14 @@ def run_forever(self):
450457
self._run_once()
451458
if self._stopping:
452459
break
460+
except BaseException as ex:
461+
self._forever_fut.set_exception(ex)
462+
self._forever_fut._log_traceback = False
463+
raise ex
464+
else:
465+
self._forever_fut.set_result(None)
453466
finally:
467+
self._forever_fut = None
454468
self._stopping = False
455469
self._thread_id = None
456470
events._set_running_loop(None)

asyncio/events.py

+3
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,9 @@ def get_debug(self):
512512
def set_debug(self, enabled):
513513
raise NotImplementedError
514514

515+
def get_forever_future(self):
516+
raise NotImplementedError
517+
515518

516519
class AbstractEventLoopPolicy:
517520
"""Abstract policy for accessing the event loop."""

asyncio/run.py

+37-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
"""asyncio.run() function."""
22

3-
__all__ = ['run']
3+
__all__ = ['run', 'forever']
44

55
import threading
66

77
from . import coroutines
88
from . import events
99

1010

11+
@coroutines.coroutine
12+
def forever():
13+
"""Wait until the current event loop stops running.
14+
15+
The coroutine will return None if the loop is stopped by
16+
calling the `loop.stop()` method.
17+
18+
The coroutine will propagate any exception that caused
19+
the loop to stop;
20+
21+
It is recommended to use this coroutine with the asyncio.run()
22+
function:
23+
24+
async def coro():
25+
print('hi')
26+
try:
27+
await asyncio.forever()
28+
except KeyboardInterrupt:
29+
await asyncio.sleep(1)
30+
print('bye')
31+
32+
asyncio.run(coro())
33+
"""
34+
loop = events.get_event_loop()
35+
return (yield from loop.get_forever_future())
36+
37+
1138
def run(coro, *, debug=False):
1239
"""Run a coroutine.
1340
@@ -50,7 +77,15 @@ async def main():
5077
if debug:
5178
loop.set_debug(True)
5279

53-
result = loop.run_until_complete(coro)
80+
task = loop.create_task(coro)
81+
task.add_done_callback(lambda task: loop.stop())
82+
83+
try:
84+
loop.run_forever()
85+
except BaseException as ex:
86+
result = loop.run_until_complete(task)
87+
else:
88+
result = task.result()
5489

5590
try:
5691
# `shutdown_asyncgens` was added in Python 3.6; not all

asyncio/tasks.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ def _step(self, exc=None):
302302
def _wakeup(self, future):
303303
try:
304304
future.result()
305-
except Exception as exc:
305+
except BaseException as exc:
306306
# This may also be a cancellation.
307307
self._step(exc)
308308
else:

0 commit comments

Comments
 (0)