Python2中解决列表,字典内汉字的显示问题

Posted 不想喝水的鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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并存真是一件蛋疼的事情!

 

以上是关于Python2中解决列表,字典内汉字的显示问题的主要内容,如果未能解决你的问题,请参考以下文章

python字典中键值对的值为中文,打印成转义字符,怎么解决

python2.7测试print出汉字,报错

python2下解决json的unicode编码问题

python2.7读汉字的时候出现乱码,如何解决

使用聚合接口获取汉字数据字典

python2基础-列表,元组,字典