1. 程式人生 > 實用技巧 >Python2中解決列表,字典內漢字的顯示問題

Python2中解決列表,字典內漢字的顯示問題

 

參考文件: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並存真是一件蛋疼的事情!