Python 扭曲的xmlrpc和numpy浮点64异常

Python 扭曲的xmlrpc和numpy浮点64异常,python,numpy,twisted,xml-rpc,Python,Numpy,Twisted,Xml Rpc,我正在使用numpy向一些工作人员发送消息,然后通过twisted/XMLRPC服务器提供结果。如果结果是numpy float 64,我会得到一个异常,因为twisted可能无法处理这种类型。事实上,我用x=float(x)将结果降级为float32,一切正常。 这不是一个很好的理由,如果我忘记了在某个地方的这个变通办法,那将是一种痛苦。 你有更好的解决办法吗 服务器: from twisted.web import xmlrpc, server import numpy as np cla

我正在使用numpy向一些工作人员发送消息,然后通过twisted/XMLRPC服务器提供结果。如果结果是numpy float 64,我会得到一个异常,因为twisted可能无法处理这种类型。事实上,我用x=float(x)将结果降级为float32,一切正常。 这不是一个很好的理由,如果我忘记了在某个地方的这个变通办法,那将是一种痛苦。 你有更好的解决办法吗

服务器:

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">
回溯(最近一次呼叫最后一次):
文件“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”,第1446行,in
运行(安装程序['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”,第1092行,正在运行
pydev_imports.execfile(文件、全局、局部)#执行脚本
文件“C:\Users\Stone\Documents\FastDose\src\Beagle\Prove e test\xmlrpc_client.py”,第28行,在
打印x.测试_np()
文件“C:\Python27\lib\xmlrpclib.py”,第1224行,在调用中__
返回self.\u发送(self.\u名称,args)
文件“C:\Python27\lib\xmlrpclib.py”,第1578行,在请求中
verbose=self.\uuu verbose
请求中第1264行的文件“C:\Python27\lib\xmlrpclib.py”
返回self.single\u请求(主机、处理程序、请求体、详细)
文件“C:\Python27\lib\xmlrpclib.py”,第1297行,在单次请求中
返回self.parse_响应(response)
文件“C:\Python27\lib\xmlrpclib.py”,第1473行,在parse_响应中
返回u.close()
文件“C:\Python27\lib\xmlrpclib.py”,第793行,关闭
raise故障(**self.\u堆栈[0])
xmlrpclib.Fault:

这与twisted无关。如果您阅读了发布的错误消息,您会在接近尾声时看到xmlrpclib.py中出现了错误

xml rpc实现用于序列化对象。但是,xml rpc执行的编组类似于
numpy.ndarray
。转换为
float
时它工作的原因是支持内置的float类型

在提供我的解决方案之前,我应该指出,在谷歌()上很容易找到的几个地方的其他地方也有人问过同样的问题,我从那里窃取了我的答案

要执行所需操作,可以将numpy数组转换为可以序列化的内容。最简单的方法是编写展平/取消展平函数。然后在发送时调用扁平器,在接收时调用非扁平器。下面是一个例子(摘自):

更简单的做法是打电话

<the array you want to send>.tolist()
.tolist()
在发送端转换为python列表,然后调用

np.array(<the list you received>)
np.array()
在接收端

这样做的唯一缺点是,在发送和接收数据时,必须显式调用扁平化器和取消扁平化器。虽然这是一个多一点的输入,它不是很多,如果你忘记了程序会大声失败(与你已经经历的错误相同),而不是默默地做错事

我从您的问题中了解到,您不喜欢这样,而是希望找到一种方法,使numpy数组直接与xmlrpc一起工作,而无需任何显式的平坦化/取消平坦化。我认为这可能是不可能的,因为文档特别指出,唯一可以序列化的第三方对象是具有
\uuuuu dict\uuuuu
属性的新样式类,在这种情况下,键必须是字符串,值必须是其他符合条件的类型

因此,如果您想直接支持numpy数组,那么似乎必须修改xml rpc的编组工作方式。如果您可以在
ndarray
的子类中添加某种方法来支持封送,那就太好了,但看起来它不是这样工作的

我希望这有助于您了解发生了什么,以及现有解决方案为何使用显式展平/取消展平

-丹尼尔


另外,这让我对如何在python中扩展xml rpc以支持其他类型的对象感到好奇,因此我发布了相关信息。

我发现了这样一种方法:在发送结果之前,我将其传递给funcion
to_float()


尝试了很长时间使用xmlrpc传输640x480x3映像。提议的“tolist()”和“flatte”解决方案对我都不起作用。最终找到了这个解决方案:

发件人:

接收人:

transferImg = proxy.getCamPic()
rawImg = np.fromstring(transferImg.data,dtype=np.uint8) 
img = np.reshape(rawImg,(640,480,3))

我知道我的cam分辨率,硬编码对我来说不是问题。改进版的transferImg中可能包含此信息?

请显示您正在执行的操作的一些代码,以及您收到的错误消息,包括完整的回溯。否则,人们将无法提供帮助。请记住,Python的
float
类型也是双精度(64位)。(您可能正在从
numpy.float64
转换为内置类型
float
)抱歉,我编辑了添加源代码。谢谢。如果其中一个让你满意,你应该接受答案。我不明白。您在twisted邮件列表中做了一件大事,在将
ndarray
传递到xmlrpc函数之前,您不想调用任何转换函数。每个人都告诉你避免转换函数是不可能的,但是你忽略了它们。然后,最后,你发布了一个解决方案。。。使用转换函数。无论如何,这特别奇怪,因为你忽略了我发布的解决方案,使用了一个比你的更简单、更普遍可用的转换函数,即使在我做了专门的研究试图帮助你之后也是如此。使用你的帮助函数,我得到了:字符串参数预期,得到了“字节”“>@juerg此答案已有四年历史,是为Python 2编写的。您在使用Python3吗?为了澄清,我在发送方使用Python3.6/32(蟒蛇)w10/64,在接收方使用Python3.7/64(蟒蛇)w10/64。
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
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))