I tried it and it yields the same result: The assertion passes, the 
exception is None and the error is still being logged.

def done(fut):
    print("Done")
    assert fut.exception() is None

The "Done" part is printed as before.


On Friday, March 28, 2014 12:22:00 AM UTC+1, Guido van Rossum wrote:
>
> Try calling fut.exception() inside the done() callback.
>
>
> On Thu, Mar 27, 2014 at 4:18 PM, Florian Rüchel 
> <[email protected]<javascript:>
> > wrote:
>
>> Oh sorry... No it didn't solve my problem. The assertions all pass and 
>> the error messages remain. I also added logging as you recommended, but it 
>> only shows that the exception is None.
>>
>>
>> On Friday, March 28, 2014 12:16:26 AM UTC+1, Guido van Rossum wrote:
>>
>>> So does this solve your problem or not? You didn't say...
>>>
>>>
>>> On Thu, Mar 27, 2014 at 4:15 PM, Florian Rüchel <[email protected]>wrote:
>>>
>>>> I modified the code a little, so I make sure it is done and has no 
>>>> exception:
>>>>
>>>> def done(fut):
>>>>     print("Future is done")
>>>> for task in conn_tasks:
>>>>     task.add_done_callback(done)
>>>> done, pending = yield from asyncio.wait(conn_tasks, timeout=5)
>>>> assert not pending
>>>> for task in done:
>>>>     assert task.exception() is None
>>>>     assert task.result() is None
>>>>
>>>> This executes cleanly, without throwing an exception and prints "Future 
>>>> is done" for each connection.
>>>>
>>>> On Friday, March 28, 2014 12:07:41 AM UTC+1, Guido van Rossum wrote:
>>>>
>>>>> Looks to me like you're never asking for the result of those Futures 
>>>>> you're passing to asyncio.wait(). It waits until the Futures are 
>>>>> complete, 
>>>>> but it doesn't inspect whether they have errors. You need something like
>>>>>
>>>>> for task in done:
>>>>>     if task.exception(): ...log it...
>>>>>
>>>>>
>>>>> On Thu, Mar 27, 2014 at 3:19 PM, Florian Rüchel 
>>>>> <[email protected]>wrote:
>>>>>
>>>>>> I can post the code, I just thought it might be too much. However, 
>>>>>> I'll just post the relevant section. Contrary to multithreaded 
>>>>>> programming 
>>>>>> here most of the times the local section is enough (I love asyncio :))
>>>>>>
>>>>>> Anyways here is the main function:
>>>>>>
>>>>>> try:
>>>>>>     self.event_loop.run_forever()
>>>>>> except KeyboardInterrupt:
>>>>>>     exit_main_loop()
>>>>>> finally:
>>>>>>      print("Running shutdown cleanup")
>>>>>>     collector.cancel()
>>>>>>
>>>>>>     @asyncio.coroutine
>>>>>>     def shutdown():
>>>>>>         yield from self.connection_pool.close()
>>>>>>     self.event_loop.run_until_complete(shutdown())
>>>>>>     self.event_loop.close()
>>>>>>
>>>>>> And the close method:
>>>>>>
>>>>>> @asyncio.coroutine
>>>>>> def close(self):
>>>>>>     try:
>>>>>>         if self.returned_connections:
>>>>>>             msg = ("Not all connections were returned: %s"
>>>>>>                    % self.returned_connections)
>>>>>>             log.error(msg)
>>>>>>             raise ValueError(msg)
>>>>>>     finally:
>>>>>>         conn_tasks = [asyncio.Task(conn.disconnect())
>>>>>>                       for conn in self.all_connections]
>>>>>>         done, pending = yield from asyncio.wait(conn_tasks, timeout=5)
>>>>>>         assert not pending
>>>>>>
>>>>>> Relevant is the finally part: I wrap each connection in a task and 
>>>>>> wait for them together. Removing the timeout did not help (I didn't 
>>>>>> expect 
>>>>>> it would, no exception is raised).
>>>>>>
>>>>>> Per existing connection (up to 10) a message is produced:
>>>>>>
>>>>>> 2014-03-27 23:11:58,143 ERROR[asyncio] Coroutine 'disconnect' defined 
>>>>>> at /path/to/library/connection.py:109 was never yielded from
>>>>>>
>>>>>> I have made sure that the amount of logging messages matches exactly 
>>>>>> the number of connections created (by counting the logging messages 
>>>>>> inside 
>>>>>> connection's __init__ function). In a very simple case there was only 
>>>>>> one 
>>>>>> connection, so only one error entry and only one log entry for a created 
>>>>>> connection.
>>>>>>
>>>>>> Hope this additional information helps uncover the issue. Thanks for 
>>>>>> the response.
>>>>>>
>>>>>> On Thursday, March 27, 2014 10:23:10 AM UTC+1, Florian Rüchel wrote:
>>>>>>>
>>>>>>> Hi everyone,
>>>>>>>
>>>>>>> I currently have a problem I cannot figure out. My code is running 
>>>>>>> perfectly fine, but when using "PYTHONASYNCIODEBUG=1" it reports that a 
>>>>>>> function was never yielded from per instance of that class I have. The 
>>>>>>> problem is I cannot create an example that replicates the issue and the 
>>>>>>> application is fairly large so maybe someone can give a hint on where I 
>>>>>>> might go looking. The function in question is a method of a connection 
>>>>>>> class. The class manages a TCP connection that has to send an init and 
>>>>>>> a 
>>>>>>> disconnect request. It is the disconnect method that is reported as 
>>>>>>> never 
>>>>>>> yielded from. I have log entries that prove that this function was 
>>>>>>> actually 
>>>>>>> run and I have tried wrapping it in asyncio.Task and asyncio.async and 
>>>>>>> I 
>>>>>>> also had a wrapping coroutine that *was *called and an explicit 
>>>>>>> "yield from connection.disconnect()" statement.
>>>>>>>
>>>>>>> In all three cases the proper log entries were written and the 
>>>>>>> server got the disconnect request, so I know it was properly executed. 
>>>>>>> Now 
>>>>>>> I am wondering if I have a bug in my application that is hidden 
>>>>>>> somewhere 
>>>>>>> between the layers that is repsonsible for this message. Or is it 
>>>>>>> possible 
>>>>>>> to trigger this error message even though the function was properly 
>>>>>>> called?
>>>>>>>
>>>>>>> I'd also like to note that this is *the only* method where this 
>>>>>>> happens, all other methods on all other classes are never reported as 
>>>>>>> problematic.I have checked the method against others but I cannot find 
>>>>>>> any 
>>>>>>> difference at all: They are called with yield from or as tasks, they 
>>>>>>> all 
>>>>>>> use other coroutines (the connect and disconnect method actually both 
>>>>>>> use *yield 
>>>>>>> from self.talk(...)*) and they are all properly decorated.
>>>>>>>
>>>>>>> I'm sorry I cannot provide any code examples, but since I am unable 
>>>>>>> to replicate the issue in a small sample, I fear I need further 
>>>>>>> guidance on 
>>>>>>> where to look for the issue.
>>>>>>>
>>>>>>> Many thanks in advance and Regards,
>>>>>>> Florian
>>>>>>>
>>>>>>
>>>>>
>>>>>
>>>>> -- 
>>>>> --Guido van Rossum (python.org/~guido) 
>>>>>
>>>>
>>>
>>>
>>> -- 
>>> --Guido van Rossum (python.org/~guido) 
>>>
>>
>
>
> -- 
> --Guido van Rossum (python.org/~guido) 
>

Reply via email to