參考文檔:https://www.cnblogs.com/xybaby/p/7854126.html
Python 2 中對列表和字典中的中文進行輸出的時候,都無法原樣打印
>>> l=['你好','版塊','博客','字典'] >>> print l ['\xc4\xe3\xba\xc3', '\xb0\xe6\xbf\xe9', '\xb2\xa9\xbf\xcd', '\xd7\xd6\xb5\xe4'] >>>
當前是運行在 win10 , python 2.7
>>> import sys,locale >>> sys.getdefaultencoding() 'ascii' >>> locale.getdefaultlocale() ('zh_CN', 'cp936') >>> sys.stdin.encoding 'cp936' >>> sys.stdout.encoding 'cp936'
相對的 python3的環境如下:
>>> import sys,locale >>> sys.getdefaultencoding() 'utf-8' >>> locale.getdefaultlocale() ('zh_CN', 'cp936') >>> sys.stdin.encoding 'utf-8' >>> sys.stdout.encoding 'utf-8
由此對比可得,python3的標准輸出默認utf-8所以中文輸出沒問題,但python2.7的是cp936所以輸出不是我們希望的結果。
這里列舉幾種解決方法:
str類型的中文
1、逐個打印
直接print容器中的元素
>>> l=['你好','版塊','博客','字典'] >>> for k in l: print k 你好 版塊 博客 字典
>>> for k, v in {'name': '張三'}.items():
print k,v
name 張三
對於簡單的容器對象,還是很方便的,但是對於嵌套的容器對象,就麻煩了
2、json dumps
這個方法在網上推薦的較多
>>> data = {'嚴': 1, 2: ['如'], 3:'玉'} >>> import json >>> dumped_data = json.dumps(data, encoding = 'gbk', ensure_ascii=False) >>> print dumped_data {"2": ["如"], "3": "玉", "嚴": 1}
可以看到,雖然打印出了中文,但是2 3都被加上了引號,感覺怪怪的
需要注意的是上面的兩個參數(encoing ensure_ascii), 這兩個參數都有默認參數(encoding = 'utf-8', ensure_ascii=True),跟我們這里使用的都不一樣。
ensure_ascii參數也很關鍵
>>> dumped_data = json.dumps(data, encoding = 'gbk')
>>> print dumped_data
{"2": ["\u5982"], "3": "\u7389", "\u4e25": 1}
python document是有描述的;
If ensure_ascii is True (the default), all non-ASCII characters in the output are escaped with \uXXXX sequences, and the result is a str instance consisting of ASCII characters only.
3、repr string_escape
>>> decoded_data = repr(data).decode('string_escape') >>> print decoded_data {2: ['如'], 3: '玉', '嚴': 1}
既然repr的輸出是十六進制的str,那么就可以使用string_escape進行轉換,具體也可以參見上文
4、PEP3140
雖然PEP3140被reject了,但我們還是可以利用其思想吧,那就是強制調用str.__str__而不是str.__repr__
class ForceStr(str): def __repr__(self): return super(ForceStr, self).__str__() def switch_container( data ): ret = None if isinstance(data, str): ret = ForceStr(data) elif isinstance(data, list) or isinstance(data, tuple): ret = [switch_container(var) for var in data] elif isinstance(data, dict): ret = dict((switch_container(k), switch_container(v)) for k, v in data.iteritems()) else: ret = data return ret
>>> switched_data = switch_container(data) >>> print switched_data {2: [如], 3: 玉, 嚴: 1} >>> switched_data {2: [如], 3: 玉, 嚴: 1}
unicode類型的中文
基本姿勢於上一章節是一樣的,下面直接給出答案
同上第二種姿勢
>>> udata = {u'嚴': 1, 2: [u'如'], 3:u'玉'}
>>> print json.dumps(udata, encoding = 'gbk', ensure_ascii=False)
{"2": ["如"], "3": "玉", "嚴": 1}
同上第三種姿勢
>>> print repr(udata).decode('unicode_escape')
{2: [u'如'], 3: u'玉', u'嚴': 1}
>>>
同上第四種姿勢
1 def switch_container( data ): 2 ret = None 3 if isinstance(data, unicode): 4 ret = ForceStr(data.encode(sys.stdout.encoding)) 5 elif isinstance(data, list) or isinstance(data, tuple): 6 ret = [switch_container(var) for var in data] 7 elif isinstance(data, dict): 8 ret = dict((switch_container(k), switch_container(v)) for k, v in data.iteritems()) 9 else: 10 ret = data 11 return ret
>>>
>>> print switch_container(udata)
{2: [如], 3: 玉, 嚴: 1}
當str與unicode中文並存時
同上第二種姿勢
>>> data[4] = u'啊'
>>> print json.dumps(data, encoding = 'gbk', ensure_ascii=False)
{"2": ["如"], "3": "玉", "4": "啊", "嚴": 1}
同上第三種姿勢
>>> print repr(data).decode('string_escape')
{2: ['如'], 3: '玉', 4: u'\u554a', '嚴': 1}
呃,unicode中文打印不出來
>>> print repr(data).decode('unicode_escape')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'gbk' codec can't encode character u'\xc8' in position 6: illegal multibyte sequence
>>>
擦,也許有正確的姿勢,不過我沒有試出來
同上第四種姿勢
1 def switch_container( data ): 2 ret = None 3 if isinstance(data, str): 4 ret = ForceStr(data) 5 elif isinstance(data, unicode): 6 ret = ForceStr(data.encode(sys.stdout.encoding)) 7 elif isinstance(data, list) or isinstance(data, tuple): 8 ret = [switch_container(var) for var in data] 9 elif isinstance(data, dict): 10 ret = dict((switch_container(k), switch_container(v)) for k, v in data.iteritems()) 11 else: 12 ret = data 13 return ret
>>> print switch_container(data)
{2: [如], 3: 玉, 4: 啊, 嚴: 1}
總結
json.dumps版本還算可以,能夠處理str中文,unicode中文, str與unicode中文並存三種情況,不過顯示結果與真實有點差異
string_escape(unicode_escape)只使用只有str(unicode)中文的情況,使用較為受限
自己實現的switch_container版本,能夠友好支持str中文,unicode中文,str與unicode中文並存三種情況
str與unicode並存真是一件蛋疼的事情!