Try calling fut.exception() inside the done() callback.

On Thu, Mar 27, 2014 at 4:18 PM, Florian Rüchel
<[email protected]>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