Weird behaviour with exceptions
Closed this issue · 4 comments
Consider the following code :
import asyncio
from PyQt5.QtCore import QTimer
import logging
import quamash
from quamash import QApplication
class Bug():
def __init__(self):
pass
@asyncio.coroutine
def errorlvl3(self):
raise TypeError()
@asyncio.coroutine
def errorlvl2(self):
yield from self.errorlvl3()
@asyncio.coroutine
def errorlvl1(self):
yield from self.errorlvl2()
def go(self):
asyncio.async(self.wait_and_close())
asyncio.async(self.errorlvl1())
@asyncio.coroutine
def wait_and_close(self):
for i in range(0, 3):
yield from asyncio.sleep(1)
self.lp.stop()
def test_bug(self):
self.qapplication = QApplication([])
self.lp = quamash.QEventLoop(self.qapplication)
self.lp.set_debug(True)
asyncio.set_event_loop(self.lp)
with self.lp:
QTimer.singleShot(0, self.go)
self.lp.run_forever()
asyncio.set_event_loop(None)
if __name__ == '__main__':
logging.basicConfig(format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
level=logging.DEBUG)
Bug().test_bug()
When I run this, I get the following output :
/home/inso/.pyenv/versions/cutecoin/bin/python3 /home/inso/code/quamash/bug.py -d
DEBUG:selector_events:__init__:Using selector: _Selector
DEBUG:__init__:add_reader:Adding reader callback for file descriptor 10
DEBUG:__init__:run_forever:Starting Qt event loop
DEBUG:__init__:call_later:Registering callback <bound method Task._step of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:30> created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/base_events.py:212>> to be invoked with arguments () after 0 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Task._step() created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 0
DEBUG:__init__:call_later:Registering callback <bound method Task._step of <Task pending coro=<errorlvl1() running at /home/inso/code/quamash/bug.py:22> created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/base_events.py:212>> to be invoked with arguments () after 0 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Task._step() created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 0
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Task._step() created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:call_later:Registering callback <bound method Future._set_result_unless_cancelled of <Future pending created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>> to be invoked with arguments (None,) after 1 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 1
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Task._step() created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:call_later:Registering callback <bound method Task._wakeup of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:33> wait_for=<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490> created at /home/inso/code/quamash/bug.py:27>> to be invoked with arguments (<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>,) after 0 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 0
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:call_later:Registering callback <bound method Future._set_result_unless_cancelled of <Future pending created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>> to be invoked with arguments (None,) after 1 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 1
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:call_later:Registering callback <bound method Task._wakeup of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:33> wait_for=<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490> created at /home/inso/code/quamash/bug.py:27>> to be invoked with arguments (<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>,) after 0 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 0
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:call_later:Registering callback <bound method Future._set_result_unless_cancelled of <Future pending created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>> to be invoked with arguments (None,) after 1 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 1
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:call_later:Registering callback <bound method Task._wakeup of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:33> wait_for=<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490> created at /home/inso/code/quamash/bug.py:27>> to be invoked with arguments (<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>,) after 0 second(s)
DEBUG:__init__:_add_callback:Adding callback <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/__init__.py:346> with delay 0
DEBUG:__init__:upon_timeout:Callback timer fired, calling <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/__init__.py:346>
DEBUG:__init__:stop:Stopping event loop...
DEBUG:__init__:stop:Stopped event loop
DEBUG:__init__:run_forever:Qt event loop ended with result 0
DEBUG:__init__:stop:Already stopped
DEBUG:__init__:close:Closing event loop...
DEBUG:__init__:remove_reader:Removing reader callback for file descriptor 10
DEBUG:base_events:close:Close <QEventLoop running=False closed=False debug=True>
DEBUG:_unix:close:Closing
DEBUG:__init__:default_exception_handler:Default exception handler executing
ERROR:__init__:__log_error:Task exception was never retrieved
future: <Task finished coro=<errorlvl1() done, defined at /home/inso/code/quamash/bug.py:22> exception=TypeError() created at /home/inso/code/quamash/bug.py:28>
source_traceback: [('/home/inso/code/quamash/bug.py', 51, '<module>', 'Bug().test_bug()'), ('/home/inso/code/quamash/bug.py', 44, 'test_bug', 'self.lp.run_forever()'), ('/home/inso/code/quamash/quamash/__init__.py', 271, 'run_forever', 'rslt = self.__app.exec_()'), ('/home/inso/code/quamash/bug.py', 28, 'go', 'asyncio.async(self.errorlvl1())')]
Traceback (most recent call last):
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py", line 238, in _step
result = next(coro)
File "/home/inso/code/quamash/bug.py", line 24, in errorlvl1
yield from self.errorlvl2()
File "/home/inso/code/quamash/bug.py", line 20, in errorlvl2
yield from self.errorlvl3()
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/coroutines.py", line 141, in coro
res = func(*args, **kw)
File "/home/inso/code/quamash/bug.py", line 16, in errorlvl3
raise TypeError()
TypeError
Process finished with exit code 0
What we can see here, is that the exception is only displayed when the loop closes. Shouldn't the exception be displayed during the "wait_and_close" method ?
probably. Have you tried with a standard event loop?
also, loop.call_soon(self.go)
should do what you want w/o getting a qtimer
involved (it will use a qtimer under the covers of course).
On Thu, Nov 5, 2015 at 1:17 PM, Insoleet notifications@github.com wrote:
Consider the following code :
import asynciofrom PyQt5.QtCore import QTimerimport loggingimport quamashfrom quamash import QApplication
class Bug():
def init(self):
pass@asyncio.coroutine def errorlvl3(self): raise TypeError() @asyncio.coroutine def errorlvl2(self): yield from self.errorlvl3() @asyncio.coroutine def errorlvl1(self): yield from self.errorlvl2() def go(self): asyncio.async(self.wait_and_close()) asyncio.async(self.errorlvl1()) @asyncio.coroutine def wait_and_close(self): for i in range(0, 3): yield from asyncio.sleep(1) self.lp.stop() def test_bug(self): self.qapplication = QApplication([]) self.lp = quamash.QEventLoop(self.qapplication) self.lp.set_debug(True) asyncio.set_event_loop(self.lp) with self.lp: QTimer.singleShot(0, self.go) self.lp.run_forever() asyncio.set_event_loop(None)
if name == 'main':
logging.basicConfig(format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
level=logging.DEBUG)
Bug().test_bug()When I run this, I get the following output :
/home/inso/.pyenv/versions/cutecoin/bin/python3 /home/inso/code/quamash/bug.py -d
DEBUG:selector_events:init:Using selector: _Selector
DEBUG:init:add_reader:Adding reader callback for file descriptor 10
DEBUG:init:run_forever:Starting Qt event loop
DEBUG:init:call_later:Registering callback <bound method Task._step of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:30> created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/base_events.py:212>> to be invoked with arguments () after 0 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Task._step() created at /home/inso/code/quamash/quamash/init.py:346> with delay 0
DEBUG:init:call_later:Registering callback <bound method Task._step of <Task pending coro=<errorlvl1() running at /home/inso/code/quamash/bug.py:22> created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/base_events.py:212>> to be invoked with arguments () after 0 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Task._step() created at /home/inso/code/quamash/quamash/init.py:346> with delay 0
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Task._step() created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:call_later:Registering callback <bound method Future._set_result_unless_cancelled of <Future pending created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>> to be invoked with arguments (None,) after 1 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/init.py:346> with delay 1
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Task._step() created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:call_later:Registering callback <bound method Task._wakeup of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:33> wait_for=<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490> created at /home/inso/code/quamash/bug.py:27>> to be invoked with arguments (<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>,) after 0 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/init.py:346> with delay 0
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:call_later:Registering callback <bound method Future._set_result_unless_cancelled of <Future pending created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>> to be invoked with arguments (None,) after 1 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/init.py:346> with delay 1
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:call_later:Registering callback <bound method Task._wakeup of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:33> wait_for=<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490> created at /home/inso/code/quamash/bug.py:27>> to be invoked with arguments (<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>,) after 0 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/init.py:346> with delay 0
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:call_later:Registering callback <bound method Future._set_result_unless_cancelled of <Future pending created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>> to be invoked with arguments (None,) after 1 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/init.py:346> with delay 1
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Future._set_result_unless_cancelled(None) created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:call_later:Registering callback <bound method Task._wakeup of <Task pending coro=<wait_and_close() running at /home/inso/code/quamash/bug.py:33> wait_for=<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490> created at /home/inso/code/quamash/bug.py:27>> to be invoked with arguments (<Future finished result=None created at /home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py:490>,) after 0 second(s)
DEBUG:init:_add_callback:Adding callback <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/init.py:346> with delay 0
DEBUG:init:upon_timeout:Callback timer fired, calling <Handle Task._wakeup(<Future finis.../tasks.py:490>) created at /home/inso/code/quamash/quamash/init.py:346>
DEBUG:init:stop:Stopping event loop...
DEBUG:init:stop:Stopped event loop
DEBUG:init:run_forever:Qt event loop ended with result 0
DEBUG:init:stop:Already stopped
DEBUG:init:close:Closing event loop...
DEBUG:init:remove_reader:Removing reader callback for file descriptor 10
DEBUG:base_events:close:Close
DEBUG:_unix:close:Closing
DEBUG:init:default_exception_handler:Default exception handler executing
ERROR:init:log_error:Task exception was never retrieved
future: <Task finished coro=<errorlvl1() done, defined at /home/inso/code/quamash/bug.py:22> exception=TypeError() created at /home/inso/code/quamash/bug.py:28>
source_traceback: [('/home/inso/code/quamash/bug.py', 51, '', 'Bug().test_bug()'), ('/home/inso/code/quamash/bug.py', 44, 'test_bug', 'self.lp.run_forever()'), ('/home/inso/code/quamash/quamash/__init.py', 271, 'run_forever', 'rslt = self._app.exec()'), ('/home/inso/code/quamash/bug.py', 28, 'go', 'asyncio.async(self.errorlvl1())')]
Traceback (most recent call last):
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py", line 238, in _step
result = next(coro)
File "/home/inso/code/quamash/bug.py", line 24, in errorlvl1
yield from self.errorlvl2()
File "/home/inso/code/quamash/bug.py", line 20, in errorlvl2
yield from self.errorlvl3()
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/coroutines.py", line 141, in coro
res = func(_args, *_kw)
File "/home/inso/code/quamash/bug.py", line 16, in errorlvl3
raise TypeError()
TypeErrorProcess finished with exit code 0
What we can see here, is that the exception is only displayed when the
loop closes. Shouldn't the exception be displayed during the
"wait_and_close" method ?—
Reply to this email directly or view it on GitHub
#52.
Yes with standard loop the behaviour is correct :
import asyncio
from PyQt5.QtCore import QTimer
import logging
import quamash
from quamash import QApplication
class Bug():
def __init__(self):
pass
@asyncio.coroutine
def errorlvl3(self):
raise TypeError()
@asyncio.coroutine
def errorlvl2(self):
yield from self.errorlvl3()
@asyncio.coroutine
def errorlvl1(self):
yield from self.errorlvl2()
def go(self):
asyncio.async(self.wait_and_close())
asyncio.async(self.errorlvl1())
@asyncio.coroutine
def wait_and_close(self):
for i in range(0, 3):
yield from asyncio.sleep(1)
self.lp.stop()
def test_bug(self):
#self.qapplication = QApplication([])
self.lp = asyncio.get_event_loop()#quamash.QEventLoop(self.qapplication)
self.lp.set_debug(True)
asyncio.set_event_loop(self.lp)
#with self.lp:
self.lp.call_soon(self.go)
self.lp.run_forever()
asyncio.set_event_loop(None)
if __name__ == '__main__':
logging.basicConfig(format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
level=logging.DEBUG)
Bug().test_bug()
/home/inso/.pyenv/versions/cutecoin/bin/python3 /home/inso/code/quamash/bug.py -d
DEBUG:selector_events:__init__:Using selector: EpollSelector
ERROR:base_events:default_exception_handler:Task exception was never retrieved
future: <Task finished coro=<errorlvl1() done, defined at /home/inso/code/quamash/bug.py:20> exception=TypeError() created at /home/inso/code/quamash/bug.py:26>
source_traceback: Object created at (most recent call last):
File "/home/inso/code/quamash/bug.py", line 49, in <module>
Bug().test_bug()
File "/home/inso/code/quamash/bug.py", line 42, in test_bug
self.lp.run_forever()
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/base_events.py", line 276, in run_forever
self._run_once()
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/base_events.py", line 1164, in _run_once
handle._run()
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/events.py", line 120, in _run
self._callback(*self._args)
File "/home/inso/code/quamash/bug.py", line 26, in go
asyncio.async(self.errorlvl1())
Traceback (most recent call last):
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/tasks.py", line 238, in _step
result = next(coro)
File "/home/inso/code/quamash/bug.py", line 22, in errorlvl1
yield from self.errorlvl2()
File "/home/inso/code/quamash/bug.py", line 18, in errorlvl2
yield from self.errorlvl3()
File "/home/inso/.pyenv/versions/3.4.3/lib/python3.4/asyncio/coroutines.py", line 141, in coro
res = func(*args, **kw)
File "/home/inso/code/quamash/bug.py", line 14, in errorlvl3
raise TypeError()
TypeError
INFO:base_events:_run_once:poll 999.396 ms took 1001.060 ms: timeout
INFO:base_events:_run_once:poll 999.761 ms took 1001.074 ms: timeout
INFO:base_events:_run_once:poll 999.799 ms took 1001.069 ms: timeout
DEBUG:base_events:close:Close <_UnixSelectorEventLoop running=False closed=False debug=True>
Process finished with exit code 0
Here is a unit test :
import asyncio
from PyQt5.QtCore import QTimer
import logging
import quamash
import unittest
from quamash import QApplication
class Bug(unittest.TestCase):
def setUp(self):
self.excepted = False
def except_hook(self, lp, ctx):
self.excepted = True
lp.default_exception_handler(ctx)
@asyncio.coroutine
def errorlvl3(self):
raise TypeError()
@asyncio.coroutine
def errorlvl2(self):
yield from self.errorlvl3()
@asyncio.coroutine
def errorlvl1(self):
yield from self.errorlvl2()
def go(self):
asyncio.async(self.wait_and_close())
asyncio.async(self.errorlvl1())
@asyncio.coroutine
def wait_and_close(self):
for i in range(0, 3):
yield from asyncio.sleep(1)
self.lp.stop()
def test_bug(self):
self.qapplication = QApplication([])
#self.lp = asyncio.get_event_loop()
self.lp = quamash.QEventLoop(self.qapplication)
self.lp.set_exception_handler(self.except_hook)
self.lp.set_debug(True)
asyncio.set_event_loop(self.lp)
with self.lp:
self.lp.call_soon(self.go)
self.lp.run_forever()
asyncio.set_event_loop(None)
self.assertTrue(self.excepted)
if __name__ == '__main__':
logging.basicConfig(format='%(levelname)s:%(module)s:%(funcName)s:%(message)s',
level=logging.DEBUG)
unittest.main()
It fails with quamash event loop but success with standard asyncio event loop.
Sorry, false positive. Didn't have the good commits on my fork, this bug was fixed a long time ago. You can close it.