在Python中设置sax解析器的编码

2024-06-02 13:00:33 发布

您现在位置:Python中文网/ 问答频道 /正文

当我将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)

…我得到以下信息:

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)

我可能遗漏了一些显而易见的东西。如何将解析器的编码从“ascii”更改为“utf-8”?


Tags: 实例inpytestparser编码feedline
3条回答

Python 2.6中的SAX解析器应该能够解析utf-8而不会损坏它。尽管您省略了与解析器一起使用的content handler,但如果该内容处理程序尝试将任何非ascii字符打印到控制台,则会导致崩溃。

例如,假设我有一个XML文档:

<?xml version="1.0" encoding="utf-8"?>
<test>
   <name>Champs-Élysées</name>
</test>

这个解析设备:

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)

这将很好地解析,而且内容确实将保留XML中的重音字符。唯一的问题是我已经注释掉的def characters()中的那一行。在Python2.6的控制台中运行时,这将产生您看到的异常,因为打印函数必须将字符转换为ascii进行输出。

您有3种可能的解决方案:

一个:确保终端支持unicode,然后在site-packages中创建一个sitecustomize.py条目,并将默认字符集设置为utf-8:

导入系统 sys.setdefaultencoding('utf-8')

2:不要将输出打印到终端(开玩笑地说)

:使用unicodedata.normalize将输出规范化,以将非ascii字符转换为ascii等价字符,或使用encode将字符转换为ascii文本输出:ch.encode('ascii', 'replace')。当然,使用这种方法,您将无法正确评估文本。

使用上面的选项1,您的代码在Python2.5中对my运行得很好。

贾雷特·哈迪已经解释了这个问题。但是,对于那些正在为命令行编写代码,并且似乎没有“sys.setdefaultencoding”可见的人,解决此错误(或“功能”)的快速方法是:

import sys
reload(sys)
sys.setdefaultencoding('utf-8')

希望reload(sys)不会破坏其他任何东西。

此旧博客中的更多详细信息:

The Illusive setdefaultencoding

您的代码在Python2.6中失败,但在3.0中有效。

这在2.6中确实有效,可能是因为它允许解析器自己计算编码(可能通过读取XML文件第一行指定的可选编码,或者默认为utf-8):

def test(filename):
    parser = xml.sax.make_parser()
    parser.parse(open(filename))

相关问题 更多 >