Why does asyncio.wait_for() need a timeout?

Frank Millman frank at chagford.com
Sat Nov 25 00:14:14 EST 2017


"Ian Kelly"  wrote in message 
news:CALwzidmRpFrR5MrEJJyZ+BDgtqLwy-sP+A_ZC6zQ7EBaZ9GUHw at mail.gmail.com...
>
> On Fri, Nov 24, 2017 at 6:31 AM, Frank Millman <frank at chagford.com> wrote:
> > "Frank Millman"  wrote in message news:ov5v3s$bv7$1 at blaine.gmane.org...
> >
> >> Below is a simple asyncio loop that runs two background tasks.
> >>
> > [...]
> >>
> >>
> >> Both take an optional timeout.
> >>
> >> If I use the first method without a timeout, the cancellation completes
> >> and the loop stops.
> >>
> >> If I use the second method without a timeout, the future is cancelled, 
> >> but
> >> the program hangs.
> >>
> >> If I add a timeout to the second one, it behaves the same as the first
> >> one.
> >>
> >> Is there a reason for this?
> >>
> >
> > I have figured out half of the answer.
> >
> > 'timeout' is an optional argument when using wait(), but a required one 
> > when
> > using wait_for().
> >
> > Therefore asyncio is raising an exception.
> >
> > However, I do not understand why no traceback appears.
>
> Here's the output I get when I try it and then interrupt with Ctrl-C:
>
> $ python3 test.py
> From 1: 1
> From 2: 1
> From 1: 2
> From 2: 2
> From 1: 3
> From 2: 3
> From 1: 4
> From 2: 4
> From 1: 5
> From 2: 5
> From 1: 6
> counter1 cancelled
> ^CTraceback (most recent call last):
>   File "test.py", line 27, in <module>
>     loop.run_forever()
>   File "/usr/lib/python3.5/asyncio/base_events.py", line 345, in 
> run_forever
>     self._run_once()
>   File "/usr/lib/python3.5/asyncio/base_events.py", line 1276, in 
> _run_once
>     event_list = self._selector.select(timeout)
>   File "/usr/lib/python3.5/selectors.py", line 441, in select
>     fd_event_list = self._epoll.poll(timeout, max_ev)
> KeyboardInterrupt
> Task exception was never retrieved
> future: <Task finished coro=<counter2() done, defined at test.py:13>
> exception=TypeError("wait_for() missing 1 required positional
> argument: 'timeout'",)>
> Traceback (most recent call last):
>   File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
>     result = coro.send(None)
>   File "test.py", line 20, in counter2
>     await asyncio.wait_for(cnt1)  # hangs
> TypeError: wait_for() missing 1 required positional argument: 'timeout'
>
>
> The unhandled exception is shown as a warning when the loop exits. It
> can't be shown prior to that because there could be some other task,
> even one that hasn't been scheduled yet, that might try to get the
> result of the counter2 task and handle the exception.
>

Thanks, Ian. All is clear now.

I was testing on Windows. I have never got Ctrl-C to work on Windows, so I 
use Ctrl-Pause, which crashes the interpreter and returns immediately, 
without showing any pending tracebacks.

I have now tested my program on Linux, and I get the same result as you.

Frank





More information about the Python-list mailing list