2012-07-19 35 views
25

我注意到這個問題,當最近更新運行Ubuntu的計算機和Python的默認版本更改爲2.7。爲什麼json.dumps(list(np.arange(5)))失敗,而json.dumps(np.arange(5).tolist())工作

import json 
import numpy as np 

json.dumps(list(np.arange(5))) # Fails, throws a "TypeError: 0 is not JSON serializable" 
json.dumps(np.arange(5).tolist()) # Works 

numpy數組的list()和tolist()方法之間有區別嗎?

+1

我看到一個類似的問題,我不能'json.dumps()'一個np.int64變量。但是,它適用於Python 2.7.9,但不適用於3.4。 – 2015-05-28 08:32:20

回答

23

它看起來像tolist()方法將numpy int32(或任何大小)回到​​int,JSON知道該怎麼辦:

>>> list(np.arange(5)) 
[0, 1, 2, 3, 4] 
>>> type(list(np.arange(5))) 
<type 'list'> 
>>> type(list(np.arange(5))[0]) 
<type 'numpy.int32'> 
>>> np.arange(5).tolist() 
[0, 1, 2, 3, 4] 
>>> type(np.arange(5).tolist()) 
<type 'list'> 
>>> type(np.arange(5).tolist()[0]) 
<type 'int'> 

作爲文檔爲tolist()說:

返回的數組作爲(可能是嵌套的)列表。

將數組數據的副本作爲(嵌套的)Python列表返回。 將數據項目 轉換爲最接近的兼容Python類型。

最後一行在這裏有所不同。

+0

你知道這是最近的變化嗎?在系統升級之前用於工作的代碼。 – azeey 2012-07-19 13:40:58

+0

不知道,我很害怕 - 甚至不知道如果改變是numpy(比如類型重命名)還是Python JSON方面(也許它用來更努力地處理未知類型?) – DSM 2012-07-19 14:57:01

+0

[簡單解決方案] (http://stackoverflow.com/questions/8230315/python-sets-are-not-json-serializable)通過顯式傳遞一個[默認處理程序](http://docs.python.org/2/library/json。 html#json.dumps)用於不可序列化的對象。 – 2013-08-22 05:41:22

24

因爲與NumPy數組的元素不是本機整數,但numpy的自己的類型:

>>> type(np.arange(5)[0]) 
<type 'numpy.int64'> 

您可以使用自定義JSONEncoder以支持arange返回ndarray類型:

import numpy as np 
import json 

class NumPyArangeEncoder(json.JSONEncoder): 
    def default(self, obj): 
     if isinstance(obj, np.ndarray): 
      return obj.tolist() # or map(int, obj) 
     return json.JSONEncoder.default(self, obj) 

print(json.dumps(np.arange(5), cls=NumPyArangeEncoder)) 
1

問題是,第一個你沒有得到一個int。你得到一個numpy.int64。這不能被序列化。