如何在Python中将UTF-8编码的文本打印到控制台<3?
我正在运行一个最新的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
环境variables。 但是Python似乎忽略了它。 至less在我的系统上,我保持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)
看到这个要点处理一个小的实用function。
如何在Python中将UTF-8编码的文本打印到控制台<3?
print u"some unicode text \N{EURO SIGN}" print b"some utf-8 encoded bytestring \xe2\x82\xac".decode('utf-8')
即如果你有一个Unicodestring,然后直接打印它。 如果你有一个string,然后将其转换为Unicode第一。
您的语言环境设置( LANG
, LC_CTYPE
)表示utf-8语言环境,因此(理论上)您可以直接打印utf-8string,并且应该在terminal中正确显示(如果terminal设置与语言环境设置一致,应该是),但是你应该避免它: 不要在你的脚本中硬编码你的环境的字符编码 ; 直接打印Unicode 。
你的问题有很多错误的假设。
您不需要使用您的语言环境设置来设置PYTHONIOENCODING
,以便将Unicode打印到terminal。 UTF-8语言环境支持所有的Unicode字符,即它的工作原理。
您不需要解决方法sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
。 如果某些代码(不受控制)确实需要打印字节和/或在将Unicode打印到Windows控制台(错误的代码页,无法打印不可解码的字符)时可能会中断,则可能会中断。 正确的语言环境设置和/或PYTHONIOENCODING
envvar就足够了。 此外,如果您需要replacesys.stdout
则使用io.TextIOWrapper()
而不是像win-unicode-console
软件包那样的codecs
模块 。
sys.getdefaultencoding()
与您的语言环境设置和PYTHONIOENCODING
。 你假设设置PYTHONIOENCODING
应该改变sys.getdefaultencoding()
是不正确的。 你应该检查sys.stdout.encoding
。
当您打印到控制台时,不会使用sys.getdefaultencoding()
。 除非设置了PYTHOHIOENCODING
否则如果将标准输出redirect到文件/pipe道,它可以用作Python 2的后备function:
$ 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")
; 它可能会以静默方式破坏您的数据并且/或者破坏不期望的第三方模块。 请记住sys.getdefaultencoding()
用于隐式地将 Python中的sys.getdefaultencoding()
str
)转换为unicode
,例如"a" + u"b"
。 另请参阅@ mesilliac的答案中的引用 。
看来完成这不是build议。
Fedorabuild议使用系统区域设置作为默认值 ,但显然这会打破其他的一些东西。
以下是邮件列表讨论的一个引用:
Python中唯一支持的默认编码是: Python 2.x:ASCII Python 3.x:UTF-8 如果你改变了这些,你就是自己的,奇怪的事情就会发生 开始发生。 默认编码不仅影响 Python和外部世界之间的翻译,也是 所有8位string和Unicode之间的内部转换。 黑客喜欢什么是在发生在潘戈模块(设置 通过重新加载站点模块,默认编码为“utf-8” 为了得到sys.setdefaultencoding()API) 彻头彻尾的错误,并会导致严重的问题,因为Unicode 对象caching它们的默认编码表示。 请不要启用基于区域的默认编码。 如果你想实现的是获得的编码 标准输出和标准input正确设置pipe道,你应该 而是改变这些(仅)的.encoding属性。 - Marc-Andre Lemburg eGenix.com
这是我如何做到的:
#!/usr/bin/python2.7 -S import sys sys.setdefaultencoding("utf-8") import site
注意-S
中的bangline。 这就告诉Python不要自动导入site
模块。 site
模块是设置默认编码和删除的方法,所以它不能再次设置。 但是会尊重已经设定的。