I would like some advice. I have encountered the following error in Python 2.6:
Traceback (most recent call last):
File "<pyshell#20>", line 1, in <module>
s.Search(query)
File "/usr/lib/python2.6/xmlrpclib.py", line 1199, in __call__
return self.__send(self.__name, args)
File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
verbose=self.__verbose
File "/usr/lib/python2.6/xmlrpclib.py", line 1253, in request
return self._parse_response(h.getfile(), sock)
File "/usr/lib/python2.6/xmlrpclib.py", line 1392, in _parse_response
return u.close()
File "/usr/lib/python2.6/xmlrpclib.py", line 838, in close
raise Fault(**self._stack[0])
Fault: <Fault 1: "<type 'exceptions.TypeError'>:dictionary key must be string">
My code is serving up part of a mini search engine using Django. In Python 3 everything runs like a dream, but Django is not available for Python 3 so I need to backdate my code, which is where the problem comes from.
My code (client.py):
# -*- coding: utf-8 -*-
from __future__ import unicode_literals # This was suggested elsewhere
import xmlrpclib
s = xmlrpclib.ServerProxy('http://localhost:11210')
data = s.Search('מלאכא') # tried prefixing with 'u'
print data
My code (Server.py):
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import pickle, sys, xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer
from SimpleXMLRPCServer import SimpleXMLRPCRequestHandler
from collections import defaultdict
docscores = pickle.load(open("docscores.pkl", "rb"))
print ("Everything loaded. No errors.")
# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
rpc_paths = ('/RPC2',)
# Create server
server = SimpleXMLRPCServer(("localhost", 11210), requestHandler=RequestHandler)
server.register_introspection_functions()
def Search(query):
results = docscores[query]
return results
server.register_function(Search, 'Search')
# Run the server's main loop
server.serve_forever()
As you can see it's pretty simple, but I get a 'dictionary key must be string' when parsing the unicode string across to the server from the client. However, the server seems quite happy and produces the following feedback, which shows it has accessed my pickled dictionary (returning a doc number and count of the ngram):
{160: 3, 417: 1, 35: 1, 133: 1, 376: 1, 193: 1, 380: 1, 363: 1, 364: 1, 126: 1, 47: 1, 145: 1, 147: 1, 382: 1, 246: 3, 121: 4, 440: 1, 441: 1, 444: 1, 280: 1}
localhost.localdomain - - [09/Aug/2011 13:32:23] "POST /RPC2 HTTP/1.0" 200 -
If I do:
type(query)
The result is:
I've also tried reload(sys), prefixing u'unicode_string', u"".join(unicode_string), and query.decode('utf-8')`, but still get this error, or end up with more errors relating to unicode/ascii decoding.
Does anyone have any ideas how I can get around this error? Or is there an alternative to XMLPRPCServer for serving data between a server instance and a client in Python 2.6?
Many thanks in advance.
The doc of xmlrpclib state that for a python dictionary to be marshaled through XML the keys should be strings:
A Python dictionary. Keys must be strings, values may be any conformable type. Objects of user-defined classes can be passed in; only their dict attribute is transmitted.
So you should change your server Search method to return a dictionary with strings as keys:
def Search(query):
results = docscores[query]
# I believe results is now a dictionary in the form {<integer>: <integer>}
return dict((str(key), value) for key, value in results.items())
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With