一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Python Unicode字符串问题理解

时间:2014-09-09 编辑:简简单单 来源:一聚教程网

这次遇到的问题还是与 Python 的 Unicode 有关。请看下面的代码:
 

 代码如下 复制代码

[~/tmp]$ cat test.py
#coding:utf8

foo = u'测试'

print foo
[~/tmp]$ python test.py
测试
[~/tmp]$ python test.py > /tmp/foobar.txt
Traceback (most recent call last):
  File "test.py", line 5, in
    print foo
UnicodeEncodeError: 'ascii' codec can't encode
  characters in position 0-1: ordinal not in range(128)

简简单单打印一个 Unicode 对象,直接输出不会报错,但重定向到文件就会挂掉,这实在让人想“呵呵”。
一番 Google 之后在 Stackoverflow 上找到了答案。原来 Python 2 里的 print 会针对 unicode 参数进行自动 encode。如果输出的目标是一个终端,它会使用终端的编码(可通过 sys.stdout.encoding 获得);如果输出的目标是管道(重定向或者使用管道符),则无法获取对应的编码,此时 Python 会使用系统默认的编码。
可以 print 一下 sys.stdout.encoding 查看终端编码:
 

 代码如下 复制代码
[~/tmp]$ python -c 'import sys; print sys.stdout.encoding'
UTF-8
[~/tmp]$ python -c 'import sys; print sys.stdout.encoding' | tee /tmp/foo.txt
None

果然在使用管道的情况下,终端编码是 None 。
解决办法也很简单,就是在 print 之前手工 encode 一下,比如在 Linux 环境完全可以一律 encode 成 UTF-8。如果想做得更好一点,也可以根据 sys.stdout.encoding 以及是否有重定向来判断决定。
刚开始写博客的时候就遇到过Unicode格式化的坑,没想到快两年后还会再遇到类似问题。不得不说 Python 2 的默认编码,以及 Unicode 和 Str 这块容易出问题。可惜的是,虽然 Python 3 完美地解决了这些问题,但都 3.X 了,还是没能大面积普及起来,真是遗憾。

热门栏目