52

我正在运行一个最近的 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 的答案) - 我只是sys.stdoutStreamWriter这样的包装:

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

有关处理它的小实用程序功能,请参见此要点

4

5 回答 5

29

似乎不建议这样做。

Fedora 建议使用系统语言环境作为默认设置,但显然这会破坏其他内容。

这是邮件列表讨论中的引述:

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
于 2012-07-31T14:54:56.557 回答
24

我就是这样做的:

#!/usr/bin/python2.7 -S

import sys
sys.setdefaultencoding("utf-8")
import site

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

于 2012-07-31T14:35:58.983 回答
10

如何在 Python < 3 中将 UTF-8 编码的文本打印到控制台?

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

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

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

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

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

您不需要解决方法sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)。如果某些代码(您无法控制)确实需要打印字节和/或在将 Unicode 打印到 Windows 控制台时可能会中断 (错误的代码页,无法打印不可解码的字符)。正确的语言环境设置和/或PYTHONIOENCODINGenvvar 就足够了。此外,如果您需要替换sys.stdout,请使用io.TextIOWrapper()而不是codecswin-unicode-console包这样的模块

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()用于在 Python 2 中隐式str转换字节串 ( ) 到/从,例如 . 另请参阅 @mesilliac 的答案中的引用unicode"a" + u"b"

于 2016-01-30T11:04:08.867 回答
5

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

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. 如何在 Python < 3 中将 UTF-8 编码的文本打印到控制台?
  2. 更改 Python 的默认编码?
  3. 在 cp1252 (Python3) 上强制使用 UTF-8
  4. 在 Cygwin 中为 Anaconda 永久设置 Python 路径
  5. https://superuser.com/questions/1374339/what-does-the-e-in-sudo-e-do
  6. 为什么 bash -c 'var=5 printf "$var"' 不打印 5?
  7. https://unix.stackexchange.com/questions/296838/whats-the-difference-between-eval-and-exec
于 2019-05-04T05:15:48.473 回答
3

While realizing the OP question is for Linux: when ending up here through a search engine, on Windows 10 the following fixes the issue:

set PYTHONIOENCODING=utf8
python myscript.py
于 2020-09-04T11:16:33.143 回答