1

I'm creating and running a bunch of async tasks in python 3.6. I'm getting ERROR Task was destroyed but it is pending! errors when my app exits because I'm failing to clean something up. I'd like to debug that.

Asyncio nicely tells me which source line created the task that's still pending, but that doesn't help me because all my tasks are created at that same point. How can I tell which task is the delayed one? I can name the tasks distinctly (adding a name attribute and using it in repr()), but the error I get from asyncio doesn't call repr() on the task. Alternatively, how can I catch the "Task destroyed" exception, or stop in pdb there?

GaryO
  • 5,873
  • 1
  • 36
  • 61
  • "Task destroyed but it is pending" might indicate the event loop being stopped while some tasks haven't had a chance to even start running, more details [here](https://stackoverflow.com/questions/40897428/please-explain-task-was-destroyed-but-it-is-pending). To debug this, you could iterate over `Task.all_tasks()` at the point where you stop the event loop (or where you close it or at program exit) and fish out the pending ones, using the custom attribute(s) to tell them apart. – user4815162342 Aug 01 '18 at 09:37
  • Yes, for sure that's exactly what's happening; the event loop is stopping while tasks are still running. But I'm not the one stopping the event loop; that's happening in my test harness somewhere. Still, your idea of checking `Task.all_tasks()` may help me; I'll try inserting that in a few likely places. I wish that error would just print the actual task though! – GaryO Aug 01 '18 at 12:54
  • 1
    Now I noticed that you can actually call `loop.set_exception_handler` to set a handler of your own. It gets called with a dict that includes the task object and the message. You can print the task, stop into `pdb`, etc. – user4815162342 Aug 01 '18 at 13:05
  • Aha, that's great, @user4815162342! If you turn that into an answer, I'll select it as correct. – GaryO Aug 01 '18 at 13:21

1 Answers1

1

The "Task destroyed but it is pending" message might indicate the event loop being stopped while some tasks haven't had a chance to even start running, such as described here.

The message is printed by the event loop, so you can debug it by registering your own handler with set_exception_handler:

import asyncio

def report(loop, context):
    if 'task' in context:
        task = context['task']
        print(context['message'])
        import pdb; pdb.set_trace()

async def dummy():
    pass

def test():
    loop = asyncio.get_event_loop()
    loop.set_exception_handler(report)
    loop.call_soon(loop.create_task, dummy())
    loop.call_soon(loop.stop)
    loop.run_forever()
    loop.close()

test()
user4815162342
  • 141,790
  • 18
  • 296
  • 355