我正在向一些员工使用numpy,然后通过twisted / XMLRPC服务器提供结果。如果结果是一个numpy浮动64,我得到一个异常原因可能扭曲无法处理这种类型。事实上,我将结果降级为float32,x = float(x),一切正常。 这不是很好的原因,如果我忘了这个workaroud某个地方,这是一个痛苦。 你有更好的解决方案吗?
服务器:
from twisted.web import xmlrpc, server
import numpy as np
class MioServer(xmlrpc.XMLRPC):
"""
An example object to be published.
"""
def xmlrpc_test_np(self):
return np.sqrt(2)
if __name__ == '__main__':
from twisted.internet import reactor
r = MioServer()
reactor.listenTCP(7080, server.Site(r))
reactor.run()
客户端:
import xmlrpclib
if __name__=='__main__':
x=xmlrpclib.ServerProxy('http://localhost:7080/')
print x.test_np()
例外:
Traceback (most recent call last):
File "C:\Users\Stone\.eclipse\org.eclipse.platform_4.3.0_1709980481_win32_win32_x86\plugins\org.python.pydev_2.8.2.2013090511\pysrc\pydevd.py", line 1446, in <module>
debugger.run(setup['file'], None, None)
File "C:\Users\Stone\.eclipse\org.eclipse.platform_4.3.0_1709980481_win32_win32_x86\plugins\org.python.pydev_2.8.2.2013090511\pysrc\pydevd.py", line 1092, in run
pydev_imports.execfile(file, globals, locals) #execute the script
File "C:\Users\Stone\Documents\FastDose\src\Beagle\Prove e test\xmlrpc_client.py", line 28, in <module>
print x.test_np()
File "C:\Python27\lib\xmlrpclib.py", line 1224, in __call__
return self.__send(self.__name, args)
File "C:\Python27\lib\xmlrpclib.py", line 1578, in __request
verbose=self.__verbose
File "C:\Python27\lib\xmlrpclib.py", line 1264, in request
return self.single_request(host, handler, request_body, verbose)
File "C:\Python27\lib\xmlrpclib.py", line 1297, in single_request
return self.parse_response(response)
File "C:\Python27\lib\xmlrpclib.py", line 1473, in parse_response
return u.close()
File "C:\Python27\lib\xmlrpclib.py", line 793, in close
raise Fault(**self._stack[0])
xmlrpclib.Fault: <Fault 8002: "Can't serialize output: cannot marshal <type 'numpy.float64'> objects">
答案 0 :(得分:1)
这与扭曲无关。如果您阅读了发布的错误消息,则会在xmlrpclib.py中看到错误发生的结尾。
xml-rpc实现使用marshal来序列化对象。但是,xml-rpc does not support handling third party objects完成了编组,例如numpy.ndarray
。转换为float
时它起作用的原因是支持内置浮点类型 。
在提供我的解决方案之前,我应该指出,在谷歌(1 2)很容易找到的几个地方已经在其他地方询问了同样的事情,我从那里偷了我的答案。
要执行您想要的操作,您可以将numpy数组转换为可序列化的数组。最简单的方法是编写flatten / unflatten函数。然后你会打电话然后在发送时调用flattener,并在接收时调用unflattener。这是一个例子(取自this post):
from cStringIO import StringIO
from numpy.lib import format
def unflatten(s):
f = StringIO(s)
arr = format.read_array(f)
return arr
def flatten(arr):
f = StringIO()
format.write_array(f, arr)
s = f.getvalue()
return s
更简单的事情就是打电话
<the array you want to send>.tolist()
在发送端转换为python列表,然后调用
np.array(<the list you received>)
在接收方。
这样做的唯一缺点是,在发送和接收数据时,必须明确调用flattener和unflattener。虽然这有点打字,但并不多,如果你忘了程序会大声失败(你已经经历过相同的错误),而不是默默地做错事。
我从你的问题中收集到你不喜欢这个,并且宁愿找到一种方法来使numpy数组直接使用xml-rpc而不需要任何明确的展平/不平整。我认为这可能是不可能的,因为xml-rpc文档明确指出可以序列化的仅第三方对象是具有__dict__
属性的新样式类,并且在这种情况下,键必须是字符串,值必须是其他符合类型。
所以你看,如果你想直接支持numpy数组,似乎你必须修改xml-rpc的编组工作方式。如果您可以将某种方法添加到ndarray
的子类以支持被编组,那将是很好的,但看起来它不是它的工作方式。
我希望这有助于您了解正在发生的事情,以及现有解决方案为何使用明确的扁平化/不平整。
-Daniel
P.S。这让我对如何在python中扩展xml-rpc以支持其他类型的对象感到好奇,所以我发布了my own question。
答案 1 :(得分:0)
我发现了这种方式:在发送结果之前,我将其传递给funcion to_float()
def iterable(x):
try:
iter(x)
except: # not iterable
return False
else: # iterable
return True
def to_float(x):
from numpy import float64,ndarray
if type(x) == dict:
res = dict()
for name in iter(x):
res[name] = to_float(x[name])
return res
elif type(x) == ndarray:
return map(float, x.tolist())
elif type(x) == float64:
return float(x)
elif iterable(x) and not isinstance(x,str):
res=[]
for item in x:
if type(item) == float64:
res.append(float(item))
elif type(x) == ndarray:
res.append(map(float, x.tolist()))
else:
res.append(item)
return res
else:
return x
答案 2 :(得分:0)
尝试了相当长的时间才能使用xmlrpc传输640x480x3图像。提议的“ tolist()”或“ flatten”解决方案都不适合我。终于找到了这个解决方案:
发件人:
def getCamPic():
cam = cv2.VideoCapture(0)
img = cam.read()
transferImg = img.tostring()
return transferImg
接收器:
transferImg = proxy.getCamPic()
rawImg = np.fromstring(transferImg.data,dtype=np.uint8)
img = np.reshape(rawImg,(640,480,3))
我知道我的凸轮分辨率,硬编码对我来说不是问题。改进的版本可能在transferImg中包含此信息?