web-dev-qa-db-ja.com

ほとんどのasyncioの例​​がloop.run_until_complete()を使用するのはなぜですか?

私は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_を使用して、複数のコルーチンを同時に実行する必要があるように感じます。

20
SamuelN

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_thingsdo_ioより前にスケジュールされていたためです。同じ出力を得るには多くの異なる方法がありますが、どちらが理にかなっているのかは、実際にアプリケーションが何をするかによって異なります。そのため、これは読者の演習として残しておきます。

24
dirn