Improve asyncio.timeout context manager documentation

Documentation for asyncio.timeout(delay=None) as async context manager is confusing re asyncio.timeout(delay=None).

  1. Listed below asyncio.Timeout(when=None)
  2. The example does not make it clear that
  • can be rescheduled with a when=absolute deadline parameter BUT
  • it’s started with a delay=relative timeout parameter
    Also it would be nice to include an example with a start time before the loop, like:
from timeit import default_timer as timer

async def main():
        start_time = timer()
        max_delay = 3600
        # Job must not run longer than 3600 seconds (one hour):
        async with asyncio.timeout(delay=max_delay) as cm:
            # We know the timeout now, so we reschedule it to 10s after start_time.
            new_deadline = start_time + 10

            await long_running_task()
    except TimeoutError:

    if cm.expired():
        print("Looks like we haven't finished on time.")

I’m not sure exactly what improvement you’re suggesting, but since your example is slightly wrong the docs could use a tweak for sure :wink: Other asyncio docs already use delay and when in the same style, though.

When dealing with absolute times (deadlines) you’re supposed to use loop.time() to base the number on, since different event loops may use different internal monotonic clocks.

However this is true for all deadlines in asyncio, most notably loop.call_at(), so I’m not sure the timeout docs are the right place for this. Maybe we could use a section for the clock stuff and then link back to it?

Thanks for having a look at this. :slight_smile:

My suggestion is to build an example that shows both the instantiation with a delay parameter (relative time) and the rescheduling with the absolute time / deadline.

Maybe also rescheduling relative to the start of the loop would be nice.
Think of awaiting asyncio.as_completed() in a for-loop which will be rescheduled as soon as the first future has resolved, for example.

The docs also use a magical get_running_loop() where I would prefer asyncio.get_running_loop() by far.