Dan*_*ver 6 python unicode sax
当我将utf-8编码的xml提供给ExpatParser实例时:
def test(filename):
parser = xml.sax.make_parser()
with codecs.open(filename, 'r', encoding='utf-8') as f:
for line in f:
parser.feed(line)
Run Code Online (Sandbox Code Playgroud)
......我得到以下内容:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 72, in search_test
parser.feed(line)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/xml/sax/expatreader.py", line 207, in feed
self._parser.Parse(data, isFinal)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xb4' in position 29: ordinal not in range(128)
Run Code Online (Sandbox Code Playgroud)
我可能在这里遗漏了一些明显的东西.如何将解析器的编码从"ascii"更改为"utf-8"?
您的代码在Python 2.6中失败,但在3.0中有效.
这在2.6中有效,大概是因为它允许解析器本身找出编码(可能通过读取XML文件第一行上可选的编码,否则默认为utf-8):
def test(filename):
parser = xml.sax.make_parser()
parser.parse(open(filename))
Run Code Online (Sandbox Code Playgroud)
Python 2.6中的SAX解析器应该能够解析utf-8而不会破坏它.虽然您已经省略了与解析器一起使用的ContentHandler,但如果该内容处理程序尝试将任何非ascii字符打印到您的控制台,则会导致崩溃.
例如,假设我有这个XML文档:
<?xml version="1.0" encoding="utf-8"?>
<test>
<name>Champs-Élysées</name>
</test>
Run Code Online (Sandbox Code Playgroud)
而这个解析装置:
import xml.sax
class MyHandler(xml.sax.handler.ContentHandler):
def startElement(self, name, attrs):
print "StartElement: %s" % name
def endElement(self, name):
print "EndElement: %s" % name
def characters(self, ch):
#print "Characters: '%s'" % ch
pass
parser = xml.sax.make_parser()
parser.setContentHandler(MyHandler())
for line in open('text.xml', 'r'):
parser.feed(line)
Run Code Online (Sandbox Code Playgroud)
这将解析得很好,内容将确实保留XML中的重音字符.唯一的问题就是def characters()我已经注释掉的那条线.在Python 2.6中运行在控制台中,这将产生您看到的异常,因为print函数必须将字符转换为ascii以进行输出.
您有3种可能的解决方案:
一:确保终端支持unicode,然后sitecustomize.py在您的终端中创建一个条目site-packages并将默认字符集设置为utf-8:
import sys sys.setdefaultencoding('utf-8')
二:不要将输出打印到终端(诙谐)
三:使用unicodedata.normalize将非ascii字符转换为ascii等效值或encode将字符转换为ascii进行文本输出来标准化输出:ch.encode('ascii', 'replace').当然,使用此方法您将无法正确评估文本.
使用上面的选项1,您的代码在我的Python 2.5中运行得很好.
小智 5
Jarret Hardie已经解释了这个问题.但是那些正在编写命令行的人,并且似乎没有"sys.setdefaultencoding"可见,快速解决这个bug(或"功能")是:
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
Run Code Online (Sandbox Code Playgroud)
希望reload(sys)不会破坏其他任何东西.
这个旧博客的更多细节: