私はasyncio
のPythonドキュメンテーション)を行っていましたが、ほとんどの例がloop.run_until_complete()
ではなくAsyncio.ensure_future()
を使用する理由を疑問に思っています。
例: https://docs.python.org/dev/library/asyncio-task.html
_ensure_future
_は、ノンブロッキング関数の利点を示すためのはるかに優れた方法のようです。一方、_run_until_complete
_は、同期関数のようにループをブロックします。
これにより、_run_until_complete
_ with loop.run_forever()
の組み合わせの代わりに_ensure_future
_を使用して、複数のコルーチンを同時に実行する必要があるように感じます。
run_until_complete
は、終了するまでフューチャーを実行するために使用されます。それに続くコードの実行をブロックします。ただし、イベントループは実行されます。スケジュールされた先物は、run_until_complete
に渡された先物が完了するまで実行されます。
この例を考えます:
import asyncio
async def do_io():
print('io start')
await asyncio.sleep(5)
print('io end')
async def do_other_things():
print('doing other things')
loop = asyncio.get_event_loop()
loop.run_until_complete(do_io())
loop.run_until_complete(do_other_things())
loop.close()
do_io
が実行されます。完了すると、do_other_things
が実行されます。出力は次のようになります。
io start
io end
doing other things
do_other_things
を実行する前にイベントループでdo_io
をスケジュールすると、前者が待機するときに、制御がdo_io
からdo_other_things
に切り替わります。
loop.create_task(do_other_things())
loop.run_until_complete(do_io())
これにより、次の出力が得られます。
doing other things
io start
io end
これは、do_other_things
がdo_io
より前にスケジュールされていたためです。同じ出力を得るには多くの異なる方法がありますが、どちらが理にかなっているのかは、実際にアプリケーションが何をするかによって異なります。そのため、これは読者の演習として残しておきます。