Seite 1 von 1

xml und UnicodeEncodeError

Verfasst: Montag 2. Januar 2012, 01:46
von Pascal
Hallo,

ich unternehm grad erste Gehversuche mit xml.
Ich will für ein Vokabelabfrageprogramm die Dateien in xml-Format speichern.

Aussehen soll die Datei so.

Code: Alles auswählen

- <woerterbuch>
- <vokabel>
  <deutsch>A</deutsch> 
  <griechisch>Α</griechisch> 
  <status>0</status> 
  <datum>2.1.2012</datum> 
  </vokabel>
[...]
Erzeugt wird die datei aus einem Dictonary der Form {deutsch: [griechisch, status, letzte abfrage]}

Der Code zum Erzeugen:

Code: Alles auswählen

import xml.dom.minidom as dom

def _erstelle_vokabel(deutsch, griechisch, status, datum):
    ''' '''
    tag_vokabel = dom.Element('vokabel')
    tag_namen = ['deutsch', 'griechisch', 'status', 'datum']
    tag_werte = [deutsch, griechisch, status, datum]
    tags = [dom.Element(t) for t in tag_namen]
   
    for name, wert, tag in zip(tag_namen, tag_werte, tags):
        text = dom.Text() 
        text.data = str(wert) 
        tag.appendChild(text)
        tag_vokabel.appendChild(tag) 

    return tag_vokabel



def schreibe_woerterbuch(d, dateiname): 
    
    tag_woerterbuch = dom.Element('woerterbuch') 
    
    for schluessel, wert in d.iteritems(): 
        tag_vokabel = _erstelle_vokabel(schluessel, *wert) 
        tag_woerterbuch.appendChild(tag_vokabel)

    baum = dom.Document()
    baum.appendChild(tag_woerterbuch)

    f = open(dateiname, "w") 
    baum.writexml(f, "", "\t", "\n") 
    f.close()
Dies funktioniert, solange ich keine Sonderzeichen verwenden. (Bei griechisch jedoch unumgänglich...)

Ich bekomme als Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "<pyshell#102>", line 1, in <module>
    schreibe_woerterbuch(d, 'testdaten.xml')
  File "C:\Python26\PyProgramme\xml_gehversuche.py", line 45, in schreibe_woerterbuch
    tag_vokabel = _erstelle_vokabel(schluessel, *wert)
  File "C:\Python26\PyProgramme\xml_gehversuche.py", line 32, in _erstelle_vokabel
    text.data = str(wert)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0391' in position 0: ordinal not in range(128)
Bei meinen Recherchen zu Codings in xml hab ich nichts hilfreiches gefunden.

Re: xml und UnicodeEncodeError

Verfasst: Montag 2. Januar 2012, 02:16
von sma
Mit `open("...", "w")` schreibst du in eine Textdatei, wobei Strings automatisch in das Encoding deiner Plattform umgewandelt werden. Eine XML-Datei musst du aber als Binärdatei schreiben. Benutze daher `open("...", "wb")`.

Ich würde auch empfehlen, im Programmtext dort, wo du "richtige" Strings hast, auch den String-Datentyp von Python zu benutzen. Bei Python 2.x ist das "unicode", denn "str" ist ein Byte-Array, wo Strings immer in einem bestimmten Encoding drin stehen. Mit der Funktion "str()" willst du unter Python 2.x ein Objekt - möglicherweise einen echten String - in ein Byte-Array konvertieren, was in deinem Fall nicht funktioniert. Unterlasse es. Nimm "unicode" oder lasse diese Zwangskonvertierung einfach weg und übergib `_erstelle_vokabel` Unicode-Strings mit `u"Äther"`.

Stefan

Re: xml und UnicodeEncodeError

Verfasst: Montag 2. Januar 2012, 11:39
von Pascal
Danke. das mit open(..., 'wb') hab ich geändert, sowie das str() durch unicode() ersetzt.
Der UnicodeEncodeError wird jetzt an einer anderen Stelle ausgelöst.

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python26\PyProgramme\xml_gehversuche.py", line 70, in <module>
    schreibe_woerterbuch(daten, 'griechisch_xml.xml')
  File "C:\Python26\PyProgramme\xml_gehversuche.py", line 54, in schreibe_woerterbuch
    baum.writexml(f, "", "\t", "\n")
 [...]
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0391' in position 3: ordinal not in range(128)
Liegt das jetzt am xml-Modul? Oder muss ich bei mir noch etwas ändern?

Meine Datei sieht jetzt so aus: http://paste.pocoo.org/show/528769/

Re: xml und UnicodeEncodeError

Verfasst: Montag 2. Januar 2012, 13:03
von Hyperion
Dein Quellcode passt nicht zur Fehlermeldung!

Ich würde anstelle des `mindom`-Moduls eher auf die ElementTree-API setzen; ok die Vorteile liegen vor allem beim Parsen und weniger beim Erstellen - aber so lernt man gleich das bessere Werkzeug kennen :-)

Dateien sollte man immer so öffnen:

Code: Alles auswählen

with open(...) as handler:
    # handler hier als File-Object zu verwenden

Re: xml und UnicodeEncodeError

Verfasst: Montag 2. Januar 2012, 19:43
von Pascal
Hyperion hat geschrieben:Dein Quellcode passt nicht zur Fehlermeldung!
Dafür kann ich ja nichts! Die Ursache für den Fehler scheint jedoch im Modul zu liegen?

ElementTree-API werd ich mir mal anschauen, aber ich fand vom Verständnis her das mindom-Modul ganz nett. Und solange keine Sonderzeichen vorhanden sind funktioniert es sehr gut.

Das open hab ich durch with open as ersetzt.

Re: xml und UnicodeEncodeError

Verfasst: Montag 2. Januar 2012, 19:46
von Hyperion
Pascal hat geschrieben:
Hyperion hat geschrieben:Dein Quellcode passt nicht zur Fehlermeldung!
Dafür kann ich ja nichts! Die Ursache für den Fehler scheint jedoch im Modul zu liegen?
Wer denn sonst? Die Meldung besagt, dass in Zeile 54 etwas schief läuft - der von Dir gezeigte Code zeigt in Zeile 54 allerdings etwas vollkommen anders ;-) Insofern ist es doch legitim nachzufragen!

Schließlich kann es ja sein, dass Du den gezeigten Code gar nicht ausprobiert hast - evtl. funzt der ja schon? Man sollte auf solche "Details" schon achten.

Re: xml und UnicodeEncodeError

Verfasst: Dienstag 3. Januar 2012, 14:58
von Pascal
Hyperion hat geschrieben:
Pascal hat geschrieben:
Hyperion hat geschrieben:Dein Quellcode passt nicht zur Fehlermeldung!
Dafür kann ich ja nichts! Die Ursache für den Fehler scheint jedoch im Modul zu liegen?
Wer denn sonst? Die Meldung besagt, dass in Zeile 54 etwas schief läuft - der von Dir gezeigte Code zeigt in Zeile 54 allerdings etwas vollkommen anders ;-) Insofern ist es doch legitim nachzufragen!
Ich habe lediglich ein paar Leerzeilen bzw. auskommentierte Zeilen oben rausgenommen. Das ändert nichts daran, dass der Fehler ausgelöst wird. Nur halt in Zeile 49 statt 54, allerdings ist das immer noch die gleiche Stelle.

Re: xml und UnicodeEncodeError

Verfasst: Dienstag 3. Januar 2012, 16:13
von Dav1d
Wir müssen die Zeile genau wissen, denn die Glaskugel funktioniert im Jahr 2012 nicht so richtig.

Re: xml und UnicodeEncodeError

Verfasst: Dienstag 3. Januar 2012, 18:39
von Hyperion
Pascal hat geschrieben: Ich habe lediglich ein paar Leerzeilen bzw. auskommentierte Zeilen oben rausgenommen. Das ändert nichts daran, dass der Fehler ausgelöst wird. Nur halt in Zeile 49 statt 54, allerdings ist das immer noch die gleiche Stelle.
Zeile 49 ist in Deinem Code eine Leerzeile :roll:

Ich habe das ganze mal um ein Encoding und den Shebang ergänzt: Link

Die dazu passende Fehlermeldung lautet:

Code: Alles auswählen

  File "./greek.py", line 64, in <module>
    schreibe_woerterbuch(daten, 'griechisch_xml.xml')
  File "./greek.py", line 48, in schreibe_woerterbuch
    baum.writexml(f, u"", u"\t", u"\n") 
  File "/usr/lib/python2.7/xml/dom/minidom.py", line 1745, in writexml
    node.writexml(writer, indent, addindent, newl)
  File "/usr/lib/python2.7/xml/dom/minidom.py", line 811, in writexml
    node.writexml(writer,indent+addindent,addindent,newl)
  File "/usr/lib/python2.7/xml/dom/minidom.py", line 811, in writexml
    node.writexml(writer,indent+addindent,addindent,newl)
  File "/usr/lib/python2.7/xml/dom/minidom.py", line 811, in writexml
    node.writexml(writer,indent+addindent,addindent,newl)
  File "/usr/lib/python2.7/xml/dom/minidom.py", line 1034, in writexml
    _write_data(writer, "%s%s%s"%(indent, self.data, newl))
  File "/usr/lib/python2.7/xml/dom/minidom.py", line 297, in _write_data
    writer.write(data)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u0391' in position 3: ordinal not in range(128)
Importiere mal das `codecs`-Modul - damit kannst Du ein Encoding bei Dateien angeben und baue Deine `schreibe_woerterbuch` so um:

Code: Alles auswählen

    with codecs.open(dateiname, "w", encoding="utf-8") as handler:
        baum.writexml(handler, u"", u"\t", u"\n") 
Ich würde dennoch zur ElementTree-API raten.

Edit: Ich hab mal ein wenig gespielt und das ganze mit der ElementTree-API umgesetzt: Link.
Leider gibt es kein `prettyprint` im Standard; aber da gibt es ja workarounds. Ansonsten kann man natürlich auch gleich auf lxml setzen.

Re: xml und UnicodeEncodeError

Verfasst: Mittwoch 4. Januar 2012, 21:08
von Pascal
wow, vielen Dank!!!

in das ElementTree-Modul werde ich mir nochmals genau anschauen.

und ich werde dann in Zukunft darauf achten, dass auch die Zeilenangabe bei der Fehlermedlung stimmt.


Eine Zeile hab ich jetzt doch noch ergänzt:

Code: Alles auswählen

## Hyperion zu verdanken