2010-10-08 37 views
3

這是一個錯誤?json.dumps(pickle.dumps(u'å'))引發UnicodeDecodeError

>>> import json 
>>> import cPickle 
>>> json.dumps(cPickle.dumps(u'å')) 
Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/__init__.py", line 230, in dumps 
    return _default_encoder.encode(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/json/encoder.py", line 361, in encode 
    return encode_basestring_ascii(o) 
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 1-3: invalid data 

回答

5

json模塊期望字符串對文本進行編碼。 Pickled數據不是文本,它是8位二進制。

一個簡單的解決方法,如果你真的需要通過JSON發送數據醃製,是使用BASE64:

j = json.dumps(base64.b64encode(cPickle.dumps(u'å'))) 
cPickle.loads(base64.b64decode(json.loads(j))) 

注意,這是很清楚一個Python錯誤。協議版本0爲明確記錄爲ASCII,但是å作爲非ASCII字節\xe5發送,而不是將其編碼爲"\u00E5"。這個錯誤在上游被報告 - 並且在錯誤得到修復的情況下關閉了門票。 http://bugs.python.org/issue2980

1

可能是泡菜中的一個bug。我的Python文檔說(所用鹹菜格式):Protocol version 0 is the original ASCII protocol and is backwards compatible with earlier versions of Python. [...] If a protocol is not specified, protocol 0 is used.


>>> cPickle.dumps(u'å').decode('ascii') 
Traceback (most recent call last): 
    File "", line 1, in 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 1: ordinal not in range(128) 

是不是沒有ASCII

和,不知道是不是它的相關性,甚至一個問題:


>>> cPickle.dumps(u'å') == pickle.dumps(u'å') 
False 
0

我使用Python2.6,你的代碼運行時沒有任何錯誤。

In [1]: import json 

In [2]: import cPickle 

In [3]: json.dumps(cPickle.dumps(u'å')) 
Out[3]: '"V\\u00e5\\np1\\n."' 

順便說一句,什麼是你的系統默認編碼,於我而言,這是

In [6]: sys.getdefaultencoding() 
Out[6]: 'ascii' 
+0

的錯誤不會在2.6.4發生我。什麼補丁版本?也許封閉和假裝 - 它的一個沒有bug的bug在2.6以後的版本中被修正了。 – 2010-10-09 00:29:54

+0

@Glenn Maynard:我正在使用2.6.5:P – satoru 2010-10-09 00:33:41

+0

無論sys.getdefaultencoding如何,也發生在2.6.6中。 'cPickle.dumps(u'å')''返回''V \ xe5 \ n.'',而不是'V \ u00e5 \ n.''。我很好奇你爲什麼返回後者(這是正確的輸出:完全是ASCII)。 – 2010-10-09 00:38:12