[Twisted-Python] Q: PyQt and error handling in Deferreds
Hello! I'm writing client application using Twisted and PyQt. I want to handle connection errors by showing the message box that describes it, so my errback looks like this: def _ebSessionRequest(self, err): QMessageBox.critical(self, "Warder", "Can't connect to server.") self.setEnabled(1) self.editAccesCode.setFocus() It works nice but when the errback fired i get two tracebacks: Traceback (most recent call last): File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 215, in errback self._startRunCallbacks(fail, 1) File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 249, in _startRunCallbacks self._runCallbacks() File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 262, in _runCallbacks self.result = callback(self.result, *args, **kw) File "main.py", line 185, in _ebSessionRequest QMessageBox.critical(self, "Warder", "Can't connect to server.") --- <exception caught here> --- File "/usr/lib/python2.2/site-packages/twisted/internet/qtreactor.py", line 74, in read why = w.doRead() File "/usr/lib/python2.2/site-packages/twisted/internet/tcp.py", line 378, in doConnect self.failIfNotConnected(error.getConnectError((connectResult, os.strerror(connectResult)))) File "/usr/lib/python2.2/site-packages/twisted/internet/tcp.py", line 315, in failIfNotConnected self.connector.connectionFailed(failure.Failure(err)) File "/usr/lib/python2.2/site-packages/twisted/internet/base.py", line 527, in connectionFailed self.factory.clientConnectionFailed(self, reason) File "/usr/lib/python2.2/site-packages/twisted/web/xmlrpc.py", line 209, in clientConnectionLost self.deferred.errback(reason) File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 215, in errback self._startRunCallbacks(fail, 1) File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 240, in _startRunCallbacks raise AlreadyCalledError() twisted.internet.defer.AlreadyCalledError: Traceback (most recent call last): File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 215, in errback self._startRunCallbacks(fail, 1) File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 249, in _startRunCallbacks self._runCallbacks() File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 262, in _runCallbacks self.result = callback(self.result, *args, **kw) File "main.py", line 185, in _ebSessionRequest QMessageBox.critical(self, "Warder", "Can't connect to server.") --- <exception caught here> --- File "/usr/lib/python2.2/site-packages/twisted/internet/qtreactor.py", line 83, in read w.connectionLost(failure.Failure(why)) File "/usr/lib/python2.2/site-packages/twisted/internet/tcp.py", line 396, in connectionLost self.failIfNotConnected(error.ConnectError()) File "/usr/lib/python2.2/site-packages/twisted/internet/tcp.py", line 315, in failIfNotConnected self.connector.connectionFailed(failure.Failure(err)) File "/usr/lib/python2.2/site-packages/twisted/internet/base.py", line 527, in connectionFailed self.factory.clientConnectionFailed(self, reason) File "/usr/lib/python2.2/site-packages/twisted/web/xmlrpc.py", line 209, in clientConnectionLost self.deferred.errback(reason) File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 215, in errback self._startRunCallbacks(fail, 1) File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 240, in _startRunCallbacks raise AlreadyCalledError() twisted.internet.defer.AlreadyCalledError: My question is: is it normal? How can I avoid such tracebacks? -- Egor Cheshkov <egor@iplus.ru>
On Tue, Jun 24, 2003 at 01:20:53PM +0400, Egor Cheshkov wrote:
Hello!
I'm writing client application using Twisted and PyQt. I want to handle connection errors by showing the message box that describes it, so my errback looks like this:
def _ebSessionRequest(self, err): QMessageBox.critical(self, "Warder", "Can't connect to server.") self.setEnabled(1) self.editAccesCode.setFocus()
It works nice but when the errback fired i get two tracebacks:
I've trimmed down the traceback to a few "interesting" lines:
Traceback (most recent call last): File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 215, in errback self._startRunCallbacks(fail, 1) [...] File "main.py", line 185, in _ebSessionRequest QMessageBox.critical(self, "Warder", "Can't connect to server.") --- <exception caught here> --- File "/usr/lib/python2.2/site-packages/twisted/internet/qtreactor.py", line 74, in read why = w.doRead() [...] File "/usr/lib/python2.2/site-packages/twisted/web/xmlrpc.py", line 209, in clientConnectionLost self.deferred.errback(reason) [...] File "/usr/lib/python2.2/site-packages/twisted/internet/defer.py", line 240, in _startRunCallbacks raise AlreadyCalledError() twisted.internet.defer.AlreadyCalledError:
And then the second traceback looks to be the same as the first.
My question is: is it normal? How can I avoid such tracebacks?
It appears that the t.web.xmlrpc.QueryFactory.clientConnectionLost handler is being called twice on the same connection, somehow. I'm guessing that creating a QMessageBox in the handler re-enters the qtreactor, but the reactor isn't re-entrant, so it re-runs the same events. Or something. Try this: def _ebSessionRequest(self, err): reactor.callLater(0, QMessageBox.critical, self, "Warder", "Can't connect to server.") self.setEnabled(1) self.editAccesCode.setFocus() Or something like it. This is mostly guesswork though, so I could easily be completely wrong about what the problem is. On a related note: perhaps we need to make the reactors smarter about accidental re-entrancy, so that weird stuff like this can't happen? -Andrew.
participants (2)
-
Andrew Bennetts
-
Egor Cheshkov