Reputation: 44345
When using xmlrpclib
in python an error on the server side is reported by the client side as an xmlrpclib.Fault
. A division by zero
error in a method on the server side (using SimpleXMLRPCServer
) usually gives an output like the following:
xmlrpclib.Fault: <Fault 1: "<type 'exceptions.ZeroDivisionError'>:integer division or modulo by zero">
This is useful as it notes the type of error, but now where it happened. How is it possible to overwrite/modify the xmlrpclib.Fault
method (in SimpleXMLRPCServer
?) so it reports the error e.g. as follows:
xmlrpclib.Fault: <Fault 1: "<type 'exceptions.ZeroDivisionError'>:integer division or modulo by zero MODULE: myMethod.py LINE: 657">
i.e. to include the name of the module the error appeared and the line number. Is that possible to do on the server-side, without raising custom exceptions? ANY error should reported in the same way on the client side.
Upvotes: 3
Views: 1726
Reputation: 1122222
If you use SimpleXMLRPCServer
, you can override the internal _marshaled_dispatch
method to add information to the Fault()
instance generated:
This is the original method:
def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
try:
params, method = xmlrpclib.loads(data)
# generate response
if dispatch_method is not None:
response = dispatch_method(method, params)
else:
response = self._dispatch(method, params)
# wrap response in a singleton tuple
response = (response,)
response = xmlrpclib.dumps(response, methodresponse=1,
allow_none=self.allow_none, encoding=self.encoding)
except:
# report low level exception back to server
# (each dispatcher should have handled their own
# exceptions)
exc_type, exc_value = sys.exc_info()[:2]
response = xmlrpclib.dumps(
xmlrpclib.Fault(1, "%s:%s" % (exc_type, exc_value)),
encoding=self.encoding, allow_none=self.allow_none)
return response
You can subclass SimpleXMLRPCServer.SimpleXMLRPCServer
and override this method:
import SimpleXMLRPCServer
import sys
import xmlrbclib
class VerboseFaultXMLRPCServer(SimpleXMLRPCServer.SimpleXMLRPCServer):
def _marshaled_dispatch(self, data, dispatch_method = None, path = None):
try:
params, method = xmlrpclib.loads(data)
# generate response
if dispatch_method is not None:
response = dispatch_method(method, params)
else:
response = self._dispatch(method, params)
# wrap response in a singleton tuple
response = (response,)
response = xmlrpclib.dumps(response, methodresponse=1,
allow_none=self.allow_none, encoding=self.encoding)
except:
# report low level exception back to server
# (each dispatcher should have handled their own
# exceptions)
exc_type, exc_value, tb = sys.exc_info()
while tb.tb_next is not None:
tb = tb.tb_next # find last frame of the traceback
lineno = tb.tb_lineno
code = tb.tb_frame.f_code
filename = code.co_filename
name = code.co_name
response = xmlrpclib.dumps(
xmlrpclib.Fault(1, "%s:%s FILENAME: %s LINE: %s NAME: %s" % (
exc_type, exc_value, filename, lineno, name)),
encoding=self.encoding, allow_none=self.allow_none)
return response
Then use VerboseFaultXMLRPCServer
instead of SimpleXMLRPCServer.SimpleXMLRPCServer
.
Upvotes: 4