从Python打印到Heroku日志时的Unicode错误
我有一个Python脚本,它在Heroku上定期运行,使用的是他们的调度程序插件。这个脚本会打印一些调试信息,但当文本中出现非ASCII字符时,我在日志中会看到这样的错误:
SyntaxError: Non-ASCII character '\xc2' in file send-tweet.py on line 40, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
这时我的脚本中有这样一行:
print u"Unicode test: £ ’ …"
我不知道该怎么处理这个问题。如果我在脚本中加上这个:
import locale
print u"Encoding: %s" % locale.getdefaultlocale()[1]
那么在日志中输出的内容是:
Encoding: UTF-8
所以,为什么它会尝试输出其他ASCII文本,但又失败了呢?
更新:顺便说一下,这是我正在使用的实际脚本。调试输出在第38-39行。
1 个回答
根据错误提示:
no encoding declared
也就是说,你的Python源文件中没有声明编码。
链接的PEP文档告诉你如何在Python源文件中声明编码:编码应该设置为你在输入示例中的unicode字符£时,编辑器或IDE使用的编码。很可能默认是UTF-8,所以在你的send-tweet.py
文件的第一行加上这个:
# coding=utf-8
如果第一行已经有类似这样的路径指令:
#!/usr/local/bin/python
那么就在第二行加上编码指令,比如:
#!/usr/local/bin/python
# coding=utf-8
另外,当你在Python源文件中写Unicode字符并声明UTF-8编码时,你必须使用一个支持UTF-8文件保存的编辑器,也就是说,编辑器需要能够把Unicode字符转换成UTF-8格式。
在这方面,请注意Unicode和UTF-8并不是同一个东西。Unicode是一个标准,而UTF-8是一种特定的编码方式,它决定了如何把Unicode字符转换成一个与ASCII兼容的字符串,并且使用1到4个字节来表示原始的Unicode字符串。
所以在Python解释器中,一个字符串可能以Unicode的形式存储,但如果你想把一个Unicode字符串写成UTF-8格式,你需要先明确地把这个字符串转换成UTF-8,比如:
s.encode("utf-8")
这点特别重要,尤其是在将Unicode字符串输出到字节流时,比如写入日志文件时,通常假设使用的是字节大小的字符,也就是对于包含非ASCII字符的内容使用UTF-8。