更新:
Python> = 3.7を使用asyncio.ensure_future
しasyncio.create_task
ている場合は、あらゆる場所で置き換えてください。これは、taskを生成するための新しい、より良い方法です。
「起動して忘れる」ためのasyncio.Task
Pythonのドキュメントによると、「バックグラウンドで」実行するasyncio.Task
コルーチンを開始することが可能です。関数によって作成されたタスクは実行をブロックしません(したがって、関数はすぐに戻ります)。これは、要求どおりに「発砲して忘れる」方法のように見えます。asyncio.ensure_future
import asyncio
async def async_foo():
print("async_foo started")
await asyncio.sleep(1)
print("async_foo done")
async def main():
asyncio.ensure_future(async_foo()) # fire and forget async_foo()
# btw, you can also create tasks inside non-async funcs
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
出力:
Do some actions 1
async_foo started
Do some actions 2
async_foo done
Do some actions 3
イベントループの完了後にタスクが実行されている場合はどうなりますか?
asyncioは、イベントループが完了した瞬間にタスクが完了することを期待していることに注意してください。したがって、次のように変更main()
する場合:
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
プログラムが終了すると、次の警告が表示されます。
Task was destroyed but it is pending!
task: <Task pending coro=<async_foo() running at [...]
これを防ぐには、イベントループが完了した後、保留中のすべてのタスクを待つだけです。
async def main():
asyncio.ensure_future(async_foo()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(0.1)
print('Do some actions 2')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also finish all running tasks:
pending = asyncio.Task.all_tasks()
loop.run_until_complete(asyncio.gather(*pending))
タスクを待つのではなく殺す
タスクが完了するのを待ちたくない場合があります(たとえば、一部のタスクが永久に実行されるように作成される場合があります)。その場合、それらを待つのではなく、単にcancel()できます。
import asyncio
from contextlib import suppress
async def echo_forever():
while True:
print("echo")
await asyncio.sleep(1)
async def main():
asyncio.ensure_future(echo_forever()) # fire and forget
print('Do some actions 1')
await asyncio.sleep(1)
print('Do some actions 2')
await asyncio.sleep(1)
print('Do some actions 3')
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
# Let's also cancel all running tasks:
pending = asyncio.Task.all_tasks()
for task in pending:
task.cancel()
# Now we should await task to execute it's cancellation.
# Cancelled task raises asyncio.CancelledError that we can suppress:
with suppress(asyncio.CancelledError):
loop.run_until_complete(task)
出力:
Do some actions 1
echo
Do some actions 2
echo
Do some actions 3
echo