【问题标题】:Python unicode in Mac os X terminalMac os X终端中的Python unicode
【发布时间】:2010-10-29 10:21:47
【问题描述】:

谁能给我解释一下这个奇怪的事情:

在 python shell 中,我输入以下西里尔字符串:

>>> print 'абвгд'
абвгд

但是当我输入时:

>>> print u'абвгд'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-9: ordinal not in range(128)

由于第一个字符串正确显示,我认为我的 OS X 终端可以表示 unicode,但事实证明在第二种情况下不能。为什么?

【问题讨论】:

    标签: python macos unicode terminal


    【解决方案1】:

    在某些控制台上显示 unicode 对象之前需要对其进行编码。试试

    u'абвгд'.encode()
    

    而不是将 unicode 编码为字符串对象(很可能使用 utf8 作为默认编码,但取决于您的 python 配置)

    【讨论】:

      【解决方案2】:

      另外,请确保终端编码设置为 Unicode/UTF-8(而不是 ascii,这似乎是您的设置):

      http://www.rift.dk/news.php?item.7.6

      【讨论】:

      • 我想到了那个,但让我烦恼的是,如果我的终端输入为普通字符串,它会正确显示 unicode - 例如'уникоде',但如果我尝试打印与 u'уникоде' 相同的字符串,则会引发错误
      【解决方案3】:

      除了确保您的 OS X 终端设置为 UTF-8 之外,您可能希望将您的 python sys 默认编码设置为 UTF-8 或更好。在/Library/Python/2.5/site-packages 中创建一个名为sitecustomize.py 的文件。在这个文件中放:

      import sys
      sys.setdefaultencoding('utf-8')
      

      setdefaultencoding 方法仅适用于站点模块,已从 sys namespace once startup has completed 中删除。因此,您需要启动一个新的 python 解释器才能使更改生效。您可以在启动后随时使用sys.getdefaultencoding() 验证当前的默认编码。

      如果字符还不是 unicode 并且您需要转换它们,请对字符串使用 decode 方法,以便将文本从其他字符集解码为 un​​icode...最好指定哪个字符集:

      s = 'абвгд'.decode('some_cyrillic_charset') # makes the string unicode
      print s.encode('utf-8') # transform the unicode into utf-8, then print it
      

      【讨论】:

      • 这解决了我的问题,虽然 repr() 解释不正确。我在我的问题中犯了一个错误(抱歉),我现在已修复 - 实际上我正在打印 u'абвгд' 字符串,所以这不是 repr() 错误。事实上 - 如果我省略 print 语句,我不会得到错误 - 我只是得到 u'\xd0\xb0\xd0\xb1\xd0\xb2\xd0\xb3\xd0\xb4' 我的猜测是默认编码- mac-roman 能够以某种方式表示西里尔字符(另一方面,这没有意义......),但不是 unicode 中的西里尔字符。我真的不明白这个:)
      • 不要更改系统默认编码;改为修复您的 Unicode 值。更改默认编码可能会破坏依赖默认行为的库。在执行此操作之前,您必须强制重新加载模块是有原因的。
      • 它对我有用,只做一个,永远解决它!
      【解决方案4】:
      >>> print 'абвгд'
      абвгд
      

      当您输入一些字符时,您的终端会决定这些字符如何呈现给应用程序。您的终端可能会将字符提供给编码为 utf-8、ISO-8859-5 甚至只有您的终端能够理解的应用程序。 Python 将这些字符作为一些字节序列获取。然后 python 按原样打印出这些字节,您的终端以某种方式解释它们以显示字符。由于您的终端通常以与之前对其进行编码相同的方式解释字节,因此所有内容都会像您输入的那样显示。

      >>> u'абвгд'
      

      在这里你输入一些作为字节序列到达 python 解释器的字符,可能由终端以某种方式编码。使用u 前缀,python 尝试将此数据转换为 unicode。要正确执行此操作,python 必须知道您的终端使用什么编码。在您的情况下,Python 猜测您的终端编码将是 ASCII,但接收到的数据不匹配,因此您收到编码错误。

      因此,在交互式会话中创建 unicode 字符串的直接方式是这样的:

      >>> us = 'абвгд'.decode('my-terminal-encoding')
      

      在文件中,您还可以使用特殊模式行指定文件的编码:

      # -*- encoding: ISO-8859-5 -*-
      us = u'абвгд'
      

      有关设置默认输入编码的其他方法,您可以查看sys.setdefaultencoding(...)sys.stdin.encoding

      【讨论】:

        【解决方案5】:

        'абвгд' 不是 unicode 字符串

        u'абвгд' 是一个 unicode 字符串

        您无法在未编码的情况下打印 unicode 字符串。当您在应用程序中处理字符串时,您希望确保任何输入都被解码并且任何输出都被编码。这样,您的应用程序将仅在内部处理 unicode 字符串并以 UTF8 输出字符串。

        供参考:

        >>> 'абвгд'.decode('utf8') == u'абвгд'
        >>> True
        

        【讨论】:

          【解决方案6】:

          从 Python 2.6 开始,您可以使用环境变量 PYTHONIOENCODING 告诉 Python 您的终端支持 UTF-8。使这个永久化的最简单方法是将以下行添加到您的~/.bash_profile

          export PYTHONIOENCODING=utf-8
          

          【讨论】:

          • 很好的例子,特别是考虑到 OSX python 构建带有微薄的sys.maxunicode == 0xffff
          • 我遇到了 sympy 漂亮打印的问题,你的技巧解决了这个问题。谢谢。
          • python -c 'print(u"\U0001F46F")'
          猜你喜欢
          • 2011-11-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-01-10
          • 2011-01-09
          • 2013-07-07
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多