zoukankan      html  css  js  c++  java
  • Python2中解决列表,字典内汉字的显示问题

     

    参考文档:https://www.cnblogs.com/xybaby/p/7854126.html

    Python 2 中对列表和字典中的中文进行输出的时候,都无法原样打印

    >>> l=['你好','版块','博客','字典']
    >>> print l
    ['xc4xe3xbaxc3', 'xb0xe6xbfxe9', 'xb2xa9xbfxcd', 'xd7xd6xb5xe4']
    >>> 

    当前是运行在 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并存真是一件蛋疼的事情!

  • 相关阅读:
    python之模块与包
    python之异常处理
    python之os与json&pickle模块
    python之random、time与sys模块
    python之re模块
    python之匿名函数、递归与二分法
    python之内置函数
    python之迭代器、生成器及列表推导式
    python之第一对象,函数名的应用,闭包
    python之命名空间与作用域
  • 原文地址:https://www.cnblogs.com/bxhsdy/p/13303997.html
Copyright © 2011-2022 走看看