影响编码、解码和打印的 python 设置列表是什么?

Jam*_*979 4 python unicode localization utf python-unicode

当我遇到 unicode 打印问题时,我想知道应该检查什么。在我的特定情况下,我使用一个已安装的模块,该模块使用错误的编解码器打印 unicode 编码字符。

在各种情况下,有几个不同的地方会影响 python 编码和解码。具体来说,Python 在不同情况下如何处理可打印数据。

有些事情是最重要的:

  • 一般环境变量LC_ALLLANG
  • Pythonsys模块设置sys.getdefaultencoding()

我还忘记了什么?


我只对 python 3 感兴趣。

Jam*_*979 5

要检查的事情

以下是我发现的内容,按照我建议检查的顺序排列:

  • 环境变量LC_ALLLANGLC_CTYPELANGUAGE
  • Python特定的环境变量PYTHONIOENCODINGPYTHONCOERCECLOCALE
    (其影响可能受到Python解释器参数的影响-E;检查sys.flags.ignore_environment
  • Windows 特定的控制台编码PYTHONLEGACYWINDOWSSTDIO
  • Pythonsys模块
    • 函数sys.getdefaultencoding()
      (推论函数sys.setdefaultencoding已从 Python 3 中删除)
    • sys.stdin.encoding
    • sys.stdout.encoding
    • sys.stderr.encoding
  • 文件系统编码设置sys.getfilesystemencoding()
  • Python文件头coding:,如
    # -*- coding: utf-8 -*-
    
    Run Code Online (Sandbox Code Playgroud) 影响内置字符串的解析器解释。
  • locale模块
    • 函数调用locale.nl_langinfo(locale.CODESET)
      (似乎不适用于 Windows Python 3.7,适用于 Debian Python 3.5)
    • 功能locale.getdefaultlocale
    • 功能locale.getpreferredencoding
      (在某些系统上工作方式不同)
  • gettext模块及其各种设施(太多,无法全部列出)
  • 传递给某些函数的目录内容,例如gettext.install(application, directory)orgettext.bindtextdomain(domain, directory)


打印值

这是一个简短的脚本,列出了其中大部分的值:

# -*- coding: utf-8 -*-
Run Code Online (Sandbox Code Playgroud)

在三个系统上打印值

  • Windows 10 3.7
  • Debian 9 与 3.5
  • Ubuntu 14 和 3.4

在 Windows 10 上,在内置 PowerShell 终端中使用 Python 3.7,此打印

#!/usr/bin/env python3
#
# print various locale information

import locale
import os
import sys


def main():

    print("Python:")
    print("  version:", sys.version.replace("\n", " "))

    print("environment:")
    for env in (
        "LC_ALL",
        "LANG",
        "LC_CTYPE",
        "LANGUAGE",
        "PYTHONUTF8",
        "PYTHONIOENCODING",
        "PYTHONLEGACYWINDOWSSTDIO",
        "PYTHONCOERCECLOCALE",
    ):
        if env in os.environ:
            print("  \"%s\"=\"%s\"" % (env, os.environ[env]))
        else:
            print("  \"%s\" not set" % env)
    print("  -E (ignore PYTHON* environment variables) ?", bool(sys.flags.ignore_environment))

    print()
    print("sys module:")
    print("  sys.getdefaultencoding() \"%s\"" % sys.getdefaultencoding())
    print("  sys.stdin.encoding \"%s\"" % sys.stdin.encoding)
    print("  sys.stdout.encoding \"%s\"" % sys.stdout.encoding)
    print("  sys.stderr.encoding \"%s\"" % sys.stderr.encoding)
    print("  sys.getfilesystemencoding() \"%s\"" % sys.getfilesystemencoding())

    print()
    print("locale module:")
    if hasattr(locale, "nl_langinfo"):
        print("  locale.nl_langinfo(locale.CODESET) \"%s\""
            % locale.nl_langinfo(locale.CODESET))
    else:
        print("  locale.nl_langinfo not available")

    try:
        print("  locale.getencoding() \"%s\"" % locale.getencoding())
    except AttributeError:
        print("  locale.getencoding() not available")

    try:
        print("  locale.getlocale()", (locale.getlocale(),))
    except AttributeError:
        print("  locale.getlocale() not available")

    try:
        print("  locale.getpreferredencoding() \"%s\""
            % locale.getpreferredencoding())
    except AttributeError:
        print("  locale.getpreferredencoding() not available")

    try:
        print("  locale.getdefaultlocale()[1] \"%s\""
            % locale.getdefaultlocale()[1])
    except AttributeError:
        print("  locale.getdefaultlocale() not available")

if __name__ == "__main__":
    main()
Run Code Online (Sandbox Code Playgroud)

在使用 Python 3.5 的 Debian 9 上,此打印

PS> python.exe print-locale.py
environment:
-E (ignore PYTHON* environment variables) ? False
"LC_ALL" not set
"LANG" not set
"LC_CTYPE" not set
"LANGUAGE" not set
"PYTHONIOENCODING"="UTF-8"
"PYTHONLEGACYWINDOWSSTDIO" not set

sys module:
getdefaultencoding "utf-8"
sys.stdin.encoding "UTF-8"
sys.stdout.encoding "UTF-8"
sys.stderr.encoding "UTF-8"

locale:
locale.nl_langinfo not available
locale.getdefaultlocale()[1] "cp1252"
locale.ngetpreferredencoding() "cp1252"
Run Code Online (Sandbox Code Playgroud)

在使用 Python 3.4 的 Ubuntu 14.04 上,此打印

$ python print-locale.py
environment:
-E (ignore PYTHON* environment variables) ? False
"LC_ALL" not set
"LANG"="en_GB.UTF-8"
"LC_CTYPE" not set
"LANGUAGE" not set
"PYTHONIOENCODING" not set
"PYTHONLEGACYWINDOWSSTDIO" not set

sys module:
getdefaultencoding "utf-8"
sys.stdin.encoding "UTF-8"
sys.stdout.encoding "UTF-8"
sys.stderr.encoding "UTF-8"

locale:
locale.nl_langinfo(locale.CODESET) "UTF-8"
locale.getdefaultlocale()[1] "UTF-8"
locale.ngetpreferredencoding() "UTF-8"

Run Code Online (Sandbox Code Playgroud)

不幸的是,当我遇到已安装模块的 unicode 打印问题时,并不能立即明显看出哪个设置正在影响该模块。更重要的是,了解这些不同的可能参数和设置如何相互作用就更加令人困惑。有多种设置组合可供测试。

但这一点可能会帮助某人入门。

另请参阅SO Question How to set sys.stdoutcoding in Python 3?的有用答案。



需要审查的相关 PEP


这篇 pymotw 文章python how-to unicodepython sys modulepython locale module提供了一些帮助。