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)

Reply via email to