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)
