Last active
February 16, 2021 13:16
-
-
Save evertrol/47325e62f8caae1b72ee to your computer and use it in GitHub Desktop.
Asyncio: cancel a set of coroutines from another coroutine, by stopping the event loop
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Example to cancel a set of asyncio coroutines (futures), | |
using one coroutine to signal the event loop to stop. | |
""" | |
import asyncio | |
import logging | |
from datetime import datetime | |
from concurrent.futures import CancelledError | |
logging.basicConfig(level=logging.DEBUG) | |
@asyncio.coroutine | |
def poll(incr=1): | |
"""A continuous coroutine.""" | |
i = 0 | |
while True: | |
print("Polling at {} seconds.".format(i)) | |
i += incr | |
yield from asyncio.sleep(incr) | |
@asyncio.coroutine | |
def stop(duration): | |
"""The coroutine to listen for signal to stop the event loop.""" | |
# In practice, a signal of sorts (e.g., through a TCP socket) may | |
# be send here to indicate a full stop | |
yield from asyncio.sleep(duration) | |
# Alternatively, one can raise an Exception and use | |
# `return_when=asyncio.FIRST_EXCEPTION` in `asyncio.wait`. | |
def main(): | |
loop = asyncio.get_event_loop() | |
# For Python 3.4.4, use `ensure_future` instead of `async` below | |
tasks = [asyncio.async(poll(2)), | |
asyncio.async(poll(1.4)), | |
asyncio.async(stop(5))] | |
finished, pending = loop.run_until_complete( | |
asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)) | |
logging.debug(">> Finished: {}", finished) | |
logging.debug(">> Pending: {}", pending) | |
# Cancel the remaining tasks | |
for task in pending: | |
logging.info("Cancelling %s: %s", task, task.cancel()) | |
try: | |
loop.run_until_complete(asyncio.gather(*pending)) | |
except CancelledError: # Any other exception would be bad | |
for task in pending: | |
logging.debug("Cancelled %s: %s", task, task.cancelled()) | |
# Stop and clean up | |
loop.stop() | |
loop.close() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Finally knew how to cancell() and not warning,Thanks you!