python / asyncio

asyncio historical repository
https://docs.python.org/3/library/asyncio.html
1.04k stars 177 forks source link

Exception ignored in: <object repr() failed> when quit #423

Closed ahuigo closed 7 years ago

ahuigo commented 7 years ago

The following program sometime produces Exception ignored in: <object repr() failed> when quit

import asyncio
async def coro(name):
    await asyncio.sleep(1)
    print('coro {}: waiting for lock'.format(name))

loop = asyncio.get_event_loop()
coros = asyncio.gather(coro(1), coro(2 ))
loop.run_until_complete(coros)
loop.close()
quit()

Here is output of the program above. My platform is : Mac OS X, python3.5.2

coro 1: waiting for lock
coro 2: waiting for lock
Exception ignored in: <object repr() failed>
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/tasks.py", line 85, in __del__
AttributeError: 'NoneType' object has no attribute '_PENDING'
Exception ignored in: <object repr() failed>
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.5.2_1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/asyncio/tasks.py", line 85, in __del__
AttributeError: 'NoneType' object has no attribute '_PENDING'
Martiusweb commented 7 years ago

Hi,

I cannot reproduce the issue with python 3.5.2 on Linux.

I am not sure that why you would use quit() here: since the loop is closed and nothing else will be executed, your python script will exit anyway.

ahuigo commented 7 years ago

@Martiusweb I won't use quit() in my project , I'm just confused by this exception and I wanna figure out it. I'll close this issue since this is not a bug, but a wrong use of loop

dbivolaru commented 7 years ago

@ahui132 @Martiusweb For posterity, as I had the same issue and found #423 by searching on google, and I assume there will be some other people having similar problems.

Conclusion is you need to explicitly del your tasks to prevent these types of errors. Otherwise at the end, when all the finalizers run (order varies) it can happen that futures is already unloaded so futures._PENDING or futures.Future will not resolve properly, thus resulting in AttributeError: 'NoneType' object has no attribute '_PENDING'.

In my case both Tasks were actually FINISHED and everything was fine.

How did I find this? I have modified asyncio.Task._del_ in the following way:

    if compat.PY34:
        def __del__(self):
            if self._state == 'PENDING' and self._log_destroy_pending:
                context = {
                    'task': self,
                    'message': 'Task was destroyed but it is pending!',
                }
                if self._source_traceback:
                    context['source_traceback'] = self._source_traceback
                self._loop.call_exception_handler(context)
            try:
                futures.Future.__del__(self)
            except AttributeError:
                name = getattr(self._coro, '__qualname__', None) or getattr(self._coro, '__name__', None)
                code = getattr(self._coro, 'gi_code', None) or getattr(self._coro, 'cr_code', None)
                frame = getattr(self._coro, 'gi_frame', None) or getattr(self._coro, 'cr_frame', None)

                filename = code.co_filename
                lineno = (frame and frame.f_lineno) or code.co_firstlineno

                print('!> Finalizer error in {}() {} at {} line {}'.format(
                    name,
                    self._state,
                    filename, lineno
                ))