2014-04-10 42 views
0

我對某些員工使用numpy,然後通過twisted/XMLRPC服務器提供結果。如果結果是浮點數64,我得到一個異常,可能是因爲扭曲而無法處理這種類型。事實上,我將結果降級到float32,其中x = float(x),一切正常。 如果我在某處忘記了這項工作,這不太好,因爲這是一種痛苦。 你有更好的解決方案嗎?twisted xmlrpc和numpy float 64異常

服務器:

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"> 
+3

請出示你在做什麼一些代碼,你會得到什麼樣的錯誤信息,包括完整的追溯。否則,人們不可能提供幫助。 –

+2

爲了記錄,Python的'float'類型也是雙精度(64位)。 (您可能正在將'numpy.float64'轉換爲內置的float類型。) –

+0

對不起,我編輯過添加源代碼。謝謝。 – gerod

回答

1

這有沒有關係扭曲。如果您閱讀您發佈的錯誤消息,則會發現在xmlrpclib.py中出現錯誤時會發現錯誤。

xml-rpc實現使用marshal來序列化對象。但是,通過xml-rpc does not support handling third party objects完成的編組,如numpy.ndarray。當您轉換爲float時,它的工作原因是內置浮動類型支持

在提供我的解決方案之前,我應該指出,這個完全相同的東西已經在幾處很容易通過谷歌找到的地方問過(12),並且我從那裏竊取我的答案。

要做你想做的事,你可以將你的numpy數組轉換爲可以序列化的東西。最簡單的方法是編寫平坦/不平坦函數。然後你會打電話,然後在發送時打電話給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>) 

在接收端。

這樣做的唯一缺點是,當您發送和接收數據時,您必須顯式調用拼合器和放大器。雖然這有點多打字,但並不多,如果你忘記了程序會大聲地失敗(你已經經歷過同樣的錯誤),而不是默默做錯。

我從你的問題中收集你不喜歡這個,而寧願找到一種方法來使numpy數組直接與xml-rpc一起工作,而沒有任何明確的展平/解壓。我認爲這可能是不可能的,因爲xml-rpc文檔明確指出,可以序列化的第三方對象是具有__dict__屬性的新樣式類,在這種情況下,鍵必須是字符串,且值必須是其他適合的類型。所以你看,如果你想直接支持numpy數組,看起來你必須修改xml-rpc的編組工作方式。如果你可以在ndarray的子類中添加某種方法來支持編組,那將會很好,但看起來這不是它的工作原理。

我希望這可以幫助您瞭解正在發生的事情,以及爲什麼現有解決方案使用明確的展平/解閉。

-Daniel

P.S.這讓我對如何在python中擴展xml-rpc以支持其他類型的對象感到好奇,所以我已經發布了my own question

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 
+0

我不明白。你在扭曲的郵件列表中做了一件大事,你不希望在將'ndarray'傳遞到xmlrpc函數之前調用任何轉換函數。每個人都告訴你,避免轉換功能是不可能的,但你忽略了它們。然後,最後,您使用轉換函數發佈解決方案。無論如何,這是特別奇怪的,因爲你忽略了我發佈的解決方案,使用比你更簡單,更普遍可用的轉換函數,即使在我專門研究試圖幫助你之後。 – DanielSank