2012-08-16 21 views
2

我正在编写清理Unicode文本文件(存储为UTF-8)的脚本,我选择使用Python 3.x(3.2)而不是更流行的2.x,因为3.x应该默认为UTF-8。也许我做错了什么,但是看起来至少print语句并不是UTF-8的默认值。如果我尝试打印字符串(MSG下面是一个字符串)包含特殊字符,我仍然获得了UnicodeEncodeError这样的:为什么Python 3.2中的print()似乎默认为UTF-8?

print(label, msg) 
... in encode 
    return codecs.charmap_encode(input,self.errors,encoding_map)[0] 
UnicodeEncodeError: 'charmap' codec can't encode character '\u0968' in position 
38: character maps to <undefined> 

如果我使用的编码()方法首先(这也很好地默认为UTF -8),我可避免的错误:

print(label, msg.encode()) 

这也适用于打印对象或包含unicode字符串列表 - 这是我经常在调试的时候做的事情 - 因为STR()似乎默认为UTF- 8。但是我真的需要记住每次我想要打印(myobj)时使用print(str(myobj).encode())?如果是这样,我想我可以尝试用自己的函数来包装它,但我对处理print()支持的所有参数置换没有信心。

此外,我的脚本从一个文件加载正则表达式并逐一应用它们。申请编码()之前,我是能够打印清晰公平的控制台的东西:

msg = 'Applying regex {} of {}: {}'.format(i, len(regexes), regex._findstr) 
print(msg) 

Applying regex 5 of 15: ^\\ge[0-9]*\b([ ]+[0-9]+\.)?[ ]* 

然而,这种崩溃如果正则表达式包含文字Unicode字符,所以我第一次申请编码()的字符串。但现在的正则表达式是很难在屏幕上阅读(我怀疑我可能有类似的麻烦,如果我尝试编写代码,保存这些正则表达式回磁盘):

msg = 'Applying regex {} of {}: {}'.format(i, len(regexes), regex._findstr) 
print(msg.encode()) 

b'Applying regex 5 of 15: ^\\\\ge[0-9]*\\b([ ]+[0-9]+\\.)?[ ]*' 

我不是非常有经验尚在Python中,所以我可能会误解。任何对教程的解释或链接(对于Python 3.x来说,大部分我在网上看到的都是2.x),我们将非常感激。

+0

如果您在Windows上运行,请参阅http://stackoverflow.com/questions/4942305/why-dont-scripting-languages-output-unicode-to-the-windows-console – dan04 2012-08-16 13:29:45

+1

Python 3不会默认为UTF-8。它默认为Unicode,但这是一个完全不同的野兽。阅读或观看Ned Batchelder的真棒[Pragmatic Unicode](http://bit.ly/unipain)。 – delnan 2012-08-17 02:15:12

+0

只是为了澄清,我并没有声称Python默认为UTF-8(因为内部表示不是'编码'),但我认为,因为encode()会做,所以print()也是如此。感谢thg435澄清print()取决于输出设备。 – 2012-12-13 16:26:35

回答

6

print不默认任何编码,它只是使用输出设备(如控制台)声称支持的任何编码。您的控制台编码似乎是非Unicode的,因此print会尝试使用该编码对您的Unicode字符串进行编码,并且失败。解决这个问题的最简单方法是告诉控制台使用utf8(例如在unix系统上使用export LC_ALL=en_US.UTF-8)。

+0

谢谢;这有助于。并感谢任何与相关主题相关的人,“为什么不将脚本语言输出到Windows控制台?”。之前我曾经搜索过这个问题,但没想过在“Windows控制台”上搜索。 – 2012-08-17 07:31:18

2

更简单的处理方法是只在脚本中使用unicode,并且只在需要与“外部”世界进行交互时使用编码数据。也就是说,当你有输入来解码或输出编码。

这样做,每次你读东西,使用decode,每次你输出的东西,使用encode

对于你的正则表达式,使用re.UNICODE标志。

我知道这并不完全正确地回答你的问题,但我认为应用这种方法应该可以让你避免编码问题。

+0

我不确定“更简单”是什么意思,因为我说它使用无编码打印比使用两者更容易。另外,我还以为我已经在我的脚本和文件中“只使用unicode”。当然,数据必须在磁盘上“编码”。我以“utf-8”读取文件,所以我不认为我需要使用解码,但到目前为止,我没有看到在每个打印语句中使用编码的方法。我会看看re.UNICODE标志。 – 2012-08-16 10:02:21

+0

我表示你可能想“只使用unicode”,因为你的正则表达式似乎没有使用unicode,因此表明你可能不是“只使用unicode,尽管你可能会这样认为。” – 2012-08-16 12:37:48

+0

不,我的正则表达式都使用要么是纯文本(这是有效的unicode),要么直接包含特殊字符,它们都保存在一个UTF-8文本文件中,但是我怀疑用正则表达式反斜杠标记可能会更好。我不确定 – 2012-08-17 07:21:28