【问题标题】:How to print UTF-8 encoded text to the console in Python < 3?如何在 Python < 3 中将 UTF-8 编码的文本打印到控制台?
【发布时间】:2018-12-29 16:42:54
【问题描述】:

我正在运行一个最新的 Linux 系统,我的所有语言环境都是 UTF-8:

LANG=de_DE.UTF-8
LANGUAGE=
LC_CTYPE="de_DE.UTF-8"
LC_NUMERIC="de_DE.UTF-8"
LC_TIME="de_DE.UTF-8"
...
LC_IDENTIFICATION="de_DE.UTF-8"
LC_ALL=

现在我想将 UTF-8 编码的内容写入控制台。

现在 Python 使用 UTF-8 进行 FS 编码,但坚持使用 ASCII 作为默认编码:-(

>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> sys.getfilesystemencoding()
'UTF-8'

我认为最好的(干净的)方法是设置PYTHONIOENCODING 环境变量。但似乎 Python 忽略了它。至少在我的系统上,我一直将ascii 作为默认编码,即使在设置 envvar 之后也是如此。

# tried this in ~/.bashrc and ~/.profile (also sourced them)
# and on the commandline before running python
export PYTHONIOENCODING=UTF-8

如果我在脚本开始时执行以下操作,它仍然有效:

>>> import sys
>>> reload(sys)  # to enable `setdefaultencoding` again
<module 'sys' (built-in)>
>>> sys.setdefaultencoding("UTF-8")
>>> sys.getdefaultencoding()
'UTF-8'

但这种方法似乎不干净。那么,有什么好的方法可以做到这一点呢?

解决方法

而不是更改默认编码 - 这不是一个好主意(请参阅 mesilliac 的回答) - 我只是用 StreamWriter 包装 sys.stdout 像这样:

sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)

请参阅this gist 了解处理它的小实用函数。

【问题讨论】:

  • 也许这会起作用:#!/usr/bin/env python # -- coding: utf-8 --
  • 记得把它放在源文件的最前面。
  • 这只影响 Python 如何解释源代码中的文字字符串。 IO 编码仍然是 ASCII。
  • PYTHONIOENCODING 不会被忽略;只是,顾名思义,它是affects the encoding used for stdin/stdout/stderr,这不是您使用sys.getdefaultencoding() 检查的内容。
  • @Brutus:你是如何测试它不起作用的?它似乎对我有用。 python -c 'import sys; print sys.stdout.encoding' 提供UTF-8PYTHONIOENCODING='C' python -c 'import sys; print sys.stdout.encoding' 提供C

标签: python shell encoding utf-8 ascii


【解决方案1】:

似乎不建议这样做。

Fedora 建议using the system locale as the default, 但显然这会破坏其他东西。

这是mailing-list discussion的引述:

Python 中唯一支持的默认编码是: Python 2.x:ASCII Python 3.x:UTF-8 如果你改变这些,你就靠自己了,奇怪的事情会发生 开始发生。默认编码不仅影响 Python与外界的翻译,也 8 位字符串和 Unicode 之间的所有内部转换。 像 pango 模块中发生的事情(设置 通过重新加载站点模块,默认编码为“utf-8” 为了得到 sys.setdefaultencoding() API 回来)只是 彻头彻尾的错误,并且会导致严重的问题,因为 Unicode 对象缓存其默认编码表示。 请不要启用基于语言环境的默认编码。 如果您只想获得以下编码 stdout 和 stdin 正确设置管道,你应该 而是更改那些(仅)的 .encoding 属性。 -- 马克-安德烈·伦堡 eGenix.com

【讨论】:

    【解决方案2】:

    这就是我的做法:

    #!/usr/bin/python2.7 -S
    
    import sys
    sys.setdefaultencoding("utf-8")
    import site
    

    注意手镯线中的-S。这告诉 Python 不会自动导入 site 模块。 site 模块用于设置默认编码并删除该方法,因此无法再次设置。但会尊重已经设置的内容。

    【讨论】:

    • 您能否根据 mesilliac 给出的答案对此进行扩展?它仍然正确吗?
    • @Arafangion 我使用的方法发生在 Python 初始化的最开始。尚未创建缓存。我同意使用重新加载技巧是不好的。这是因为许多其他的东西可能已经被实例化或缓存了原始编码。因此,我想出了这种早期发生的方法。请注意,在它之前没有其他导入。它对我有用。
    • 虽然这在测试中对我有用,但我决定避免使用它。只是不清楚我是否会遇到任何副作用并且闻起来有点腥;-) 我只是用默认编码将sys.stdout 包装在StreamWriter 中(至少在现代Linux系统中应该是UTF-8): sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout).
    • 这是一个非常糟糕的主意。在过去的几周里,我解决了两个问题,这些问题通过从用户代码中删除 sys.setdefaultencoding("utf-8") 得到了解决。恕我直言,这只是掩盖了任何潜在的问题
    • @AlastairMcCormack 我使用它没有任何问题。只要你知道发生了什么,这不是问题。您认为它掩盖了哪些潜在问题?
    【解决方案3】:

    如何在 Python

    print u"some unicode text \N{EURO SIGN}"
    print b"some utf-8 encoded bytestring \xe2\x82\xac".decode('utf-8')
    

    即,如果您有一个 Unicode 字符串,则直接打印它。如果你有 一个字节串,然后先将其转换为 Unicode。

    您的语言环境设置(LANGLC_CTYPE)指示 utf-8 语言环境和 因此(理论上)你可以直接打印一个 utf-8 字节串 应该在您的终端中正确显示(如果终端设置 与区域设置一致,它们应该是)但是你 应该避免它:不要硬编码你的字符编码 脚本中的环境; 改为直接打印 Unicode

    您的问题中有许多错误的假设。

    您不需要使用您的语言环境设置设置PYTHONIOENCODING, 将 Unicode 打印到终端。 utf-8 语言环境支持所有 Unicode 字符,即它按原样工作。

    您不需要解决方法sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)。有可能 如果某些代码(您无法控制)确实需要打印字节,则中断 和/或它可能会在 printing Unicode to Windows console (wrong codepage, can't print undecodable characters)。正确的语言环境设置和/或PYTHONIOENCODING envvar 就足够了。此外,如果您需要替换 sys.stdout,那么 use io.TextIOWrapper() instead of codecs module 就像 win-unicode-console package 一样。

    sys.getdefaultencoding() 与您的区域设置无关 PYTHONIOENCODING。你假设设置PYTHONIOENCODING 应该更改sys.getdefaultencoding() 不正确。你应该 改为检查sys.stdout.encoding

    sys.getdefaultencoding() 打印到 安慰。如果 stdout 是,它可以用作 Python 2 的后备 除非设置了PYTHOHIOENCODING,否则重定向到文件/管道:

    $ python2 -c'import sys; print(sys.stdout.encoding)'
    UTF-8
    $ python2 -c'import sys; print(sys.stdout.encoding)' | cat
    None
    $ PYTHONIOENCODING=utf8 python2 -c'import sys; print(sys.stdout.encoding)' | cat
    utf8
    

    请勿拨打sys.setdefaultencoding("UTF-8");它可能会损坏您的 数据静默和/或破坏不期望的第 3 方模块 它。记住sys.getdefaultencoding()是用来转换字节串的 (str) 在 Python 2 中与unicode 之间的隐式 例如,"a" + u"b"。也可以看看, the quote in @mesilliac's answer.

    【讨论】:

      【解决方案4】:

      如果程序没有在屏幕上显示适当的字符, 即,无效符号, 使用以下命令行运行程序:

      PYTHONIOENCODING=utf8 python3 yourprogram.py
      

      如果您的程序是全局安装的模块,则如下:

      PYTHONIOENCODING=utf8 yourprogram
      

      在某些平台上,如 Cygwin(mintty.exe 终端)和 Anaconda Python(或 Python 3),只需运行 export PYTHONIOENCODING=utf8 和 后来运行程序不行, 并且您每次都需要始终执行PYTHONIOENCODING=utf8 yourprogram 才能正确运行程序。

      在 Linux 上,如果是 sudo,您可以尝试传递 -E 参数以将用户变量导出到 sudo 进程:

      export PYTHONIOENCODING=utf8
      sudo -E python yourprogram.py
      

      如果您尝试此操作但没有成功,则需要在 sudo shell 上输入:

      sudo /bin/bash
      PYTHONIOENCODING=utf8 yourprogram
      

      相关:

      1. How to print UTF-8 encoded text to the console in Python < 3?
      2. Changing default encoding of Python?
      3. Forcing UTF-8 over cp1252 (Python3)
      4. Permanently set Python path for Anaconda within Cygwin
      5. https://superuser.com/questions/1374339/what-does-the-e-in-sudo-e-do
      6. Why bash -c 'var=5 printf "$var"' does not print 5?
      7. https://unix.stackexchange.com/questions/296838/whats-the-difference-between-eval-and-exec

      【讨论】:

      • utf8 区分大小写吗?此外,唯一可能的设置utf8 还是utf-8 也有效?只是因为我看到了这么多变体......(你在你的答案中使用了其中两个!?)
      • 我认为至少对于我的 Python 3.7.2UTF-8 的使用不区分大小写,我不确定它是否忽略了 UTF-8 中的连字符。
      • 这是有道理的——我使用的是 Python 2.7.X,但我不确定要使用什么......
      【解决方案5】:

      虽然意识到 OP 问题是针对 Linux 的:当通过搜索引擎到达此处时,在 Windows 10 上,以下解决了该问题:

      set PYTHONIOENCODING=utf8
      python myscript.py
      

      【讨论】:

        猜你喜欢
        • 2012-07-29
        • 2013-12-20
        • 2014-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-09
        • 2016-11-28
        相关资源
        最近更新 更多