burli hat geschrieben:
Naja, aber sie eliminiert den Fehler und es kommt das gewünschte Ergebnis raus. Als kann es doch nicht ganz 2+1-1 sein. Mal überlegen. Ich bekomme vom XML Parser einen Unicode zurück statt eines ASCII String. Wenn ich .encode("utf-8") darauf anwende erhalte ich durchgehend Bytecode Strings
Code: Alles auswählen
<type 'str'> RX_AACK_ON
<type 'str'> TX_ARET_ON
<type 'str'> 0 µs
<type 'str'> 2 µs
Darauf nochmal .decode("utf-8") und alles passt.
Fast richtig, denn genau das ist doch das "2 + 1 - 1"
Du kannst diese Operationen def. weglassen und erhältst sofort das gewünschte Ergebnis. Wie ja schon öfter festgestellt, liefert lxml eben nur dann Byte-Strings zurück, wenn diese sich vollständig mittels ASCII codieren lassen. Da ASCII aber für so ziemlich alle Encodings (oder irre ich hier?) den "kleinsten gemeinsamen Nenner" bildet, macht das nichts. Eine implizite Wandlung, etwa durch Konkatenierung mit einem Unicode-String liefert in Python 2.x ja wieder Unicode. Da ASCII zunächst immer als Standard-Codierung angenommen wird (und bei Umstellung auf z.B. "utf-8" ja immer noch dieselben Bytewerte besitzt), funktioniert das ohne Probleme.
burli hat geschrieben:
Aber ich hatte ja vorher nur .decode("utf-8"). Also habe ich versucht, einen Unicode in Unicode zu wandeln, aber .decode() erwartet in dem Fall wohl einen Byte String und spuckt daher einen Fehler aus.
Eben! Da lag wohl Dein Problem. Dein Vorgehen war beim Auftreten des Fehlers wohl so:
Code: Alles auswählen
In [186]: u"Hallöle".decode("utf-8")
---------------------------------------------------------------------------
UnicodeEncodeError Traceback (most recent call last)
C:\Dokumente und Einstellungen\nelson\Eigene Dateien\<ipython console> in <modul
e>()
C:\Programme\Python27\lib\encodings\utf_8.py in decode(input, errors)
14
15 def decode(input, errors='strict'):
---> 16 return codecs.utf_8_decode(input, errors, True)
17
18 class IncrementalEncoder(codecs.IncrementalEncoder):
UnicodeEncodeError: 'ascii' codec can't encode character u'\x94' in position 4:
ordinal not in range(128)
In [187]: u"Hallöle".encode("utf-8").decode("utf-")
Out[187]: u'Hall\x94le'
Du hast eben nach Schirtt 186 das "encode()" dazwischengeschaltet, dabei hätte es so sofort geklappt:
burli hat geschrieben:
unicode() macht das anscheinend automatisch.
Jein. unicode() ist ja als Basisfunktion dokumentiert. Bei einem Unicode-Objekt liefert unicode exakt dasselbe Objekt zurück:
Code: Alles auswählen
In [183]: u = u"Hallo"
In [184]: unicode(u) == u
Out[184]: True
In [185]: unicode(u) is u
Out[185]: True
Und nun kommt alles zusammen: lxml liefert eben entweder Unicode-Objekte, dann würde der Aufruf von unicode() eben nichts ändern, oder aber lxml liefert Bytestrings in ASCII-Codierung. Diese kann aber eben ohne Angabe eines expliziten Encodings von Python in Unicode umgewandelt werden.
Daher meine "Idee", dein Dictionary zu erstellen, in dem neben den gewünschten Attributnamen auch eine Funktion angegeben wird, die den Inhalt entsprechend aufbereitet. Will man nichts ändern, kann man da eben auf die unicode()-Funktion zurückgreifen und Du hast dann def. Unicode-Objekte in Deinem Zielmodell. (da ja Elixir hier wohl keine implizite Konvertierung vornimmt und es dann zu der Warnung kommt, selbst wenn nur "ASCII"-Bytestrings drin stehen)