【www.bbyears.com--python】
这次遇到的问题还是与 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 查看终端编码:
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 了,还是没能大面积普及起来,真是遗憾。