[Twisted-Python] xmlrpc doesn't catch XML parsing exceptions
Andrew Dalke
dalke at dalkescientific.com
Mon Jun 2 23:05:27 MDT 2003
I used the Twisted code to connect to a URI which wasn't providing
XML-RPC
services but is providing HTML. The XML-RPC code tried to parse the
HTML response, and failed. It reported the failure correctly, but also
spewed a traceback to stdout. Here's what stdout looks like
Traceback (most recent call last):
File "E:\Python22\Lib\site-packages\twisted\internet\default.py",
line 473, in
doSelect
_logrun(selectable, _drdw, selectable, method, dict)
File "E:\Python22\Lib\site-packages\twisted\python\log.py", line 64,
in callWi
thLogger
callWithContext({"system": lp}, func, *args, **kw)
File "E:\Python22\Lib\site-packages\twisted\python\log.py", line 51,
in callWi
thContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "E:\Python22\Lib\site-packages\twisted\python\context.py", line
32, in ca
llWithContext
return func(*args,**kw)
--- <exception caught here> ---
File "E:\Python22\Lib\site-packages\twisted\internet\default.py",
line 482, in
_doReadOrWrite
why = getattr(selectable, method)()
File "E:\Python22\Lib\site-packages\twisted\internet\tcp.py", line
219, in doR
ead
return self.protocol.dataReceived(data)
File "E:\Python22\Lib\site-packages\twisted\protocols\basic.py", line
179, in
dataReceived
return self.rawDataReceived(data)
File "E:\Python22\Lib\site-packages\twisted\protocols\http.py", line
341, in r
awDataReceived
self.handleResponseEnd()
File "E:\Python22\Lib\site-packages\twisted\protocols\http.py", line
323, in h
andleResponseEnd
self.handleResponse(b)
File "E:\Python22\Lib\site-packages\twisted\web\xmlrpc.py", line 174,
in handl
eResponse
self.factory.parseResponse(contents)
File "E:\Python22\Lib\site-packages\twisted\web\xmlrpc.py", line 199,
in parse
Response
response = xmlrpclib.loads(contents)
File "E:\Python22\lib\xmlrpclib.py", line 804, in loads
p.feed(data)
File "E:\Python22\lib\xmlrpclib.py", line 390, in feed
self._parser.Parse(data, 0)
xml.parsers.expat.ExpatError: mismatched tag: line 10, column
The reason is twisted.web.xmlrpc, which has
def parseResponse(self, contents):
if not self.deferred:
return
try:
response = xmlrpclib.loads(contents)
except xmlrpclib.Fault, error:
self.deferred.errback(error)
self.deferred = None
else:
self.deferred.callback(response[0][0])
self.deferred = None
There's nothing which handles an XML parsing error.
I don't know who to blame here. I would like a
except "XML parsing error", error:
here as well, but there's no way to spell that. The xmlrpclib code
chooses
the fastest parser available, and the different parsers could throw
different
exceptions. Eg, the Expat parser throws an ExpatError, which is derived
directly from Exception, and shares no other base class with
The best I can think of now is to catch anything which isn't a "normal"
Python exception, that is
except (StandardError, SystemExit, StopIteration):
raise
except (xmlrpclib.Fault, Exception), error:
self.deferred.errback(error)
(could also use a bare except, but I think that's overkill for this
case.)
Even that's not perfect. xmllib.Error is derived from RuntimeError(!).
OTOH, that module is deprecated ....
Oh! Since Fault is derived from exception, could just catch Exception
instead of the 2-ple I have there.
Let me point out that Twisted did a good job of catching the error at a
higher
level and correctly sending it to my handler, so even if this had
occurred in
production code the app would have kept working as expected. This is
good.
Andrew
dalke at dalkescientific.com
More information about the Twisted-Python
mailing list