2009-05-13 18 views
6

में सैक्स पार्सर के लिए एन्कोडिंग सेट करना जब मैं एक ExpatParser उदाहरण के लिए एक UTF-8 एन्कोडेड XML फ़ीड:अजगर

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) 

मैं:

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) 

... मैं निम्नलिखित मिल शायद यहां कुछ स्पष्ट याद आ रही है। मैं पार्सर एन्कोडिंग को 'ascii' से 'utf-8' में कैसे बदलूं?

उत्तर

5

आपका कोड पायथन 2.6 में विफल रहता है, लेकिन 3.0 में काम करता है।

यह 2.6 में काम करते हैं, शायद क्योंकि यह पार्सर ही एन्कोडिंग यह पता लगाने की (शायद वैकल्पिक एक्सएमएल फ़ाइल की पहली पंक्ति पर निर्दिष्ट एन्कोडिंग पढ़ने, और अन्यथा utf-8 पर डिफ़ॉल्ट करके) की अनुमति देता है:

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

इस में काम किया: उदाहरण के लिए, एक की तरह latin1 साथ इनकोडिंग एक विस्तारित ASCII फ़ाइल को पार्स कर सकते हैं 2.5, भी। –

5

पायथन 2.6 में SAX पार्सर इसे उलझाने के बिना utf-8 को पार्स करने में सक्षम होना चाहिए। यद्यपि आपने कंटेंटहैंडलर को छोड़ दिया है जिसे आप पार्सर के साथ उपयोग कर रहे हैं, यदि वह सामग्री हैंडलर आपके कंसोल पर किसी भी गैर-असीसी अक्षरों को मुद्रित करने का प्रयास करता है, तो इससे क्रैश हो जाएगा।

<?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) 

यह ठीक पार्स जाएगा और सामग्री वास्तव में में उच्चारण वर्ण सुरक्षित करेगा

उदाहरण के लिए, मैं इस एक्सएमएल दस्तावेज़ है कहना एक्सएमएल। एकमात्र मुद्दा यह है कि def characters() में पंक्ति है जिसे मैंने टिप्पणी की है। पाइथन 2.6 में कंसोल में चल रहा है, यह आपके द्वारा देखे जा रहे अपवाद का उत्पादन करेगा क्योंकि प्रिंट फ़ंक्शन को अक्षरों को आउटपुट के लिए एएससीआई में परिवर्तित करना होगा।

एक:

आप 3 संभव समाधान है सुनिश्चित करें कि आपके टर्मिनल यूनिकोड का समर्थन करती है, तो अपने site-packages में एक sitecustomize.py प्रविष्टि बना सकते हैं और डिफ़ॉल्ट वर्ण utf-8 के लिए सेट सेट:

आयात sys sys.setdefaultencoding ('utf-8')

दो: टर्मिनल (जीभ में गाल)

के उत्पादन मुद्रित न करें

तीन: ch.encode('ascii', 'replace'): उत्पादन unicodedata.normalize का उपयोग कर ascii समकक्ष, या encode वर्ण पाठ उत्पादन के लिए ASCII करने के लिए गैर-ascii वर्ण परिवर्तित करने के लिए सामान्यीकृत करें। बेशक, इस विधि का उपयोग करके आप पाठ का उचित मूल्यांकन करने में सक्षम नहीं होंगे।

ऊपर विकल्प एक का उपयोग करना, अपने कोड अजगर 2.5 में मेरे लिए ठीक काम किया।

+1

मूल प्रश्न में वास्तविक समस्या टर्मिनल पर यूनिकोड प्रिंटिंग के साथ कुछ भी नहीं है। यह इस तथ्य के कारण है कि ओपी कोडेक्स.ओपेन के साथ इनपुट को पूर्व-डीकोड करना था, क्योंकि स्टीफन 202 की पहचान हुई है। – DanC

5

Jarret हार्डी पहले से ही इस मुद्दे को विस्तार से बताया। लेकिन आप में से जो लोग कमांड लाइन के लिए कोडिंग कर रहे हैं, और नहीं है "sys.setdefaultencoding" दिखाई, जल्दी इस बग के आसपास काम (या "सुविधा") है:

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

उम्मीद है कि reload(sys) कुछ और नहीं तोड़ेंगे।इस पुराने ब्लॉग में

अधिक विवरण:

The Illusive setdefaultencoding

0

janpf के जवाब पर टिप्पणी करते हुए (क्षमा करें, मैं इसे वहाँ डाल करने के लिए पर्याप्त प्रतिष्ठा नहीं है) ध्यान दें कि Janpf के संस्करण निष्क्रिय टूट जाएगा जिसके लिए आवश्यक है इसके स्वयं का stdout आदि जो sys के डिफ़ॉल्ट से अलग है। इसलिए मैं कुछ ऐसा होने के लिए कोड को संशोधित करने का सुझाव चाहते हैं:

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 

अन्य चर संरक्षित करने के लिए हो सकता है, लेकिन इन सबसे महत्वपूर्ण तरह लग रहे हैं।

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 एन्कोडिंग है कि एक एक्सएमएल फ़ाइल को पार्स की अनुमति देता है। (। जोड़ी इस जवाब सीधे इस सवाल का शीर्षक संबोधित करने के लिए, के रूप में यह खोज इंजन में उच्च रैंक जाता है) test(filename, "latin1")