xmlrpclib: ключ словаря должен быть ошибкой типа строки - PullRequest
3 голосов
/ 09 августа 2011

Я хотел бы получить совет.Я обнаружил следующую ошибку в 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">

Мой код обслуживает часть мини-поисковой системы, использующей Django.В Python 3 все работает как мечта, но Django недоступен для Python 3, поэтому мне нужно задним числом установить свой код, откуда и возникает проблема.

Мой код (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

Мой код (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()

Как вы можете видеть, это довольно просто, но я получаю «ключ словаря должен быть строкой» при разборе строки Юникода досервер от клиента.Тем не менее, сервер выглядит вполне довольным и выдает следующий отзыв, который показывает, что он получил доступ к моему маринованному словарю (возвращает номер документа и счетчик 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 -

Если я это сделаю: type (query)Результат:

Я также пытался reload(sys), с префиксом u'unicode_string', u"".join(unicode_string) и query .decode ('utf-8') `, но все равно получаю этоошибка, или в конечном итоге с большим количеством ошибок, связанных с декодированием Unicode / ASCII.

Кто-нибудь есть какие-либо идеи, как я могу обойти эту ошибку?Или есть альтернатива XMLPRPCServer для обслуживания данных между экземпляром сервера и клиентом в Python 2.6?

Заранее большое спасибо.

1 Ответ

5 голосов
/ 09 августа 2011

В документе xmlrpclib указано, что для маршалинга словаря python через XML ключами должны быть строки:

Словарь Python. Ключи должны быть строками, значения могут быть любыми совместимый тип. Объекты пользовательских классов могут быть переданы в; передается только их атрибут dict .

Таким образом, вы должны изменить свой метод поиска на сервере, чтобы он возвращал словарь со строками в качестве ключей:

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())
...