6

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」に変更するにはどうすればよいですか?

4

5 に答える 5

5

ジャレット・ハーディーはすでにこの問題を説明しています。しかし、コマンドラインをコーディングしていて、「sys.setdefaultencoding」が表示されていないように思われる方は、このバグ(または「機能」)をすばやく回避できます。

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

うまくいけばreload(sys)、他に何も壊さないでしょう。

この古いブログの詳細:

幻想的なsetdefaultencoding

于 2009-12-04T18:03:11.063 に答える
5

コードは Python 2.6 では失敗しますが、3.0 では機能します。

これは 2.6 でも機能しますが、これはおそらく、パーサー自体がエンコーディングを把握できるためです (おそらく、XML ファイルの最初の行でオプションで指定されたエンコーディングを読み取り、それ以外の場合はデフォルトで utf-8 に設定されます)。

def test(filename):
    parser = xml.sax.make_parser()
    parser.parse(open(filename))
于 2009-05-13T12:22:58.547 に答える
5

Python 2.6 の SAX パーサーは、文字化けすることなく utf-8 を解析できるはずです。パーサーで使用している ContentHandler を省略しましたが、そのコンテンツ ハンドラーが非 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()私がコメントアウトしたその行です。Python 2.6 のコンソールで実行すると、表示されている例外が生成されます。これは、print 関数が出力のために文字を ASCII に変換する必要があるためです。

考えられる解決策は 3 つあります。

1 : 端末が Unicode をサポートしていることを確認してから、sitecustomize.pyエントリを作成しsite-packages、デフォルトの文字セットを utf-8 に設定します。

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

2 : 出力を端末に出力しない (冗談)

3 : を使用して出力を正規化し、unicodedata.normalizeASCII 以外の文字を同等の ASCII に変換するかencode、文字をテキスト出力用の ASCII に変換しますch.encode('ascii', 'replace')。もちろん、この方法ではテキストを適切に評価することはできません。

上記のオプション 1 を使用すると、コードは Python 2.5 の my で問題なく動作しました。

于 2009-05-13T13:18:29.203 に答える
3

SAX パーサーに任意のファイル エンコーディングを設定するには、次のようにInputSourceを使用できます。

def test(filename, encoding):
    parser = xml.sax.make_parser()
    with open(filename, "rb") as f:
        input_source = xml.sax.xmlreader.InputSource()
        input_source.setByteStream(f)
        input_source.setEncoding(encoding)
        parser.parse(input_source)

これにより、非 ASCII、非 UTF8 エンコーディングを持つ XML ファイルを解析できます。たとえば、LATIN1 でエンコードされた拡張 ASCII ファイルを次のように解析できます。 test(filename, "latin1")

(検索エンジンで上位にランクされる傾向があるため、この質問のタイトルに直接対処するためにこの回答を追加しました。)

于 2015-11-08T19:24:21.313 に答える
0

janpfの回答にコメントすると(申し訳ありませんが、そこに置くのに十分な評判がありません)、Janpfのバージョンは、sysのデフォルトとは異なる独自のstdoutなどを必要とするIDLEを壊すことに注意してください。したがって、コードを次のように変更することをお勧めします。

import sys

currentStdOut = sys.stdout
currentStdIn = sys.stdin
currentStdErr = sys.stderr

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

sys.stdout = currentStdOut
sys.stdin = currentStdIn
sys.stderr = currentStdErr

保持する変数は他にもあるかもしれませんが、これらが最も重要なようです。

于 2012-08-20T22:27:44.757 に答える