简体   繁体   中英

Is there a difference between 'await future' and 'await asyncio.wait_for(future, None)'?

With python 3.5 or later, is there any difference between directly applying await to a future or task, and wrapping it with asyncio.wait_for ? The documentation is unclear on when it is appropriate to use wait_for and I'm wondering if it's a vestige of the old generator-based library. The test program below appears to show no difference but that doesn't really prove anything.

import asyncio

async def task_one():
    await asyncio.sleep(0.1)
    return 1

async def task_two():
    await asyncio.sleep(0.1)
    return 2

async def test(loop):
    t1 = loop.create_task(task_one())
    t2 = loop.create_task(task_two())

    print(repr(await t1))
    print(repr(await asyncio.wait_for(t2, None)))

def main():
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(test(loop))
    finally:
        loop.close()

main()

The wait_for gives two more functionalities:

  1. allow to define timeout,
  2. let you specify the loop

Your example:

await f1
await asyncio.wait_for(f1, None)  # or simply asyncio.wait_for(f1)

besides an overhead of calling additional wrapper (wait_for), they're the same ( https://github.com/python/cpython/blob/master/Lib/asyncio/tasks.py#L318 ).

Both awaits will wait indefinitely for the results (or exception). In this case plain await is more appropriate.

On the other hand if you provide timeout argument it will wait for the results with time constraint. And if it will take more than the timeout it will raise TimeoutError and the future will be cancelled.

async def my_func():
    await asyncio.sleep(10)
    return 'OK'

# will wait 10s 
await my_func()

# will wait only 5 seconds and then will raise TimeoutError
await asyncio.wait_for(my_func(), 5)

Another thing is the loop argument. In the most cases you shouldn't be bothered, the use case is limited: inject different loop for tests, run other loop ...

The problem with this parameter is, that all subsequent tasks/functions should also have that loop passed along...

More info https://github.com/python/asyncio/issues/362

Unfortunately the python documentation is a little bit unclear here, but if you have a look into the sources its pretty obvious:

In contrary to await the coroutine asyncio.wait_for() allows to wait only for a limited time until the future/task completes. If it does not complete within this time a concurrent.futures.TimeoutError is raised.

This timeout can be specified as second parameter. In your sample code this timeout parameter is None which results in exactly the same functionality as directly applying await / yield from .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM