New submission from Jack O'Connor:

The following test script prints a KeyboardInterrupt traceback (expected), but 
also an AttributeError traceback (unexpected):


import asyncio
@asyncio.coroutine
def main():
    raise KeyboardInterrupt
asyncio.get_event_loop().run_until_complete(main())


Traceback (most recent call last):
  File "test.py", line 9, in <module>
    asyncio.get_event_loop().run_until_complete(main())
  File "/usr/lib/python3.4/asyncio/base_events.py", line 203, in 
run_until_complete
    self.run_forever()
  File "/usr/lib/python3.4/asyncio/base_events.py", line 184, in run_forever
    self._run_once()
  File "/usr/lib/python3.4/asyncio/base_events.py", line 817, in _run_once
    handle._run()
  File "/usr/lib/python3.4/asyncio/events.py", line 39, in _run
    self._callback(*self._args)
  File "/usr/lib/python3.4/asyncio/tasks.py", line 321, in _step
    result = next(coro)
  File "/usr/lib/python3.4/asyncio/tasks.py", line 103, in coro
    res = func(*args, **kw)
  File "test.py", line 6, in main
    raise KeyboardInterrupt
KeyboardInterrupt
--- Logging error ---
Traceback (most recent call last):
--- Logging error ---
Traceback (most recent call last):
Exception ignored in: <bound method Task.__del__ of 
Task(<coro>)<exception=KeyboardInterrupt()>>
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/futures.py", line 184, in __del__
  File "/usr/lib/python3.4/asyncio/base_events.py", line 725, in 
call_exception_handler
  File "/usr/lib/python3.4/logging/__init__.py", line 1296, in error
  File "/usr/lib/python3.4/logging/__init__.py", line 1402, in _log
  File "/usr/lib/python3.4/logging/__init__.py", line 1412, in handle
  File "/usr/lib/python3.4/logging/__init__.py", line 1482, in callHandlers
  File "/usr/lib/python3.4/logging/__init__.py", line 846, in handle
  File "/usr/lib/python3.4/logging/__init__.py", line 977, in emit
  File "/usr/lib/python3.4/logging/__init__.py", line 899, in handleError
  File "/usr/lib/python3.4/traceback.py", line 169, in print_exception
  File "/usr/lib/python3.4/traceback.py", line 153, in _format_exception_iter
  File "/usr/lib/python3.4/traceback.py", line 18, in _format_list_iter
  File "/usr/lib/python3.4/traceback.py", line 65, in _extract_tb_or_stack_iter
  File "/usr/lib/python3.4/linecache.py", line 15, in getline
  File "/usr/lib/python3.4/linecache.py", line 41, in getlines
  File "/usr/lib/python3.4/linecache.py", line 126, in updatecache
  File "/usr/lib/python3.4/tokenize.py", line 437, in open
AttributeError: 'module' object has no attribute 'open'


The issue is that Task._step() calls self.set_exception() for both Exceptions 
and BaseExceptions, but it reraises BaseExceptions. That means that the 
BaseEventLoop never gets to call future.result() to clear the exception when 
it's a BaseException. Future.__del__ eventually tries to log this uncleared 
exception, but something about the circumstances of program exit (caused by the 
same exception) has already cleaned up the builtins needed for logging.

Is that __del__ violating some best practices for finalizers by calling such a 
complicated function? Either way, I'm not sure this case should be considered 
an "unretrieved exception" at all. It's propagating outside the event loop 
after all. Should Task._step() be setting it in the first place, if it's going 
to reraise it? Should it be set without _log_traceback=True somehow?

----------
components: asyncio
messages: 226985
nosy: gvanrossum, haypo, oconnor663, yselivanov
priority: normal
severity: normal
status: open
title: KeyboardInterrupt inside a coroutine causes AttributeError
type: behavior
versions: Python 3.4

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue22428>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to