lxml: Alternative Fehlerbehandlung für try

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hyperion hat geschrieben: Also ich habe da keine Probleme:
& steht aber nicht drin

Code: Alles auswählen

       <enumerator name="PA_BUF_LT_bitf">
          <enum val="0" text="0 &#xB5;s" constname="PA_BUF_LT_0US"/>
          <enum val="1" text="2 &#xB5;s" constname="PA_BUF_LT_2US"/>
          <enum val="2" text="4 &#xB5;s" constname="PA_BUF_LT_4US"/>
          <enum val="3" text="6 &#xB5;s" constname="PA_BUF_LT_6US"/>
        </enumerator>
Außerdem definierst du den String als Unicode. Ich hab mir mal den Typ ausgeben lassen. Es passiert also genau das, was du oben schon festgestellt hast
<type 'str'> PLL_ON (TX_ON)
<type 'str'> RX_AACK_ON
<type 'str'> TX_ARET_ON
<type 'unicode'> 0 µs
<type 'unicode'> 2 µs
<type 'unicode'> 4 µs
<type 'unicode'> 6 µs
<type 'unicode'> 2 µs
<type 'unicode'> 4 µs
<type 'unicode'> 6 µs
<type 'unicode'> 8 µs
<type 'str'> 3.0 dBm
<type 'str'> 2.8 dBm
<type 'str'> 2.3 dBm
unicode() scheint aber auch zu funktionieren
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

K.A. wieso da ein "amp" dazwischengekommen ist :K In Meiner Shell ist es nicht da ;-)

Ob ich meinen String als Unicode deklariere spielt keine Rolle, da die Zeichen eh alle ASCII-Codes sind und zudem beim Parsing Vorgang eh in Unicode (bzw. Bytestrings im ASCII-Bereich, wie am Anfang schon geklärt) gewandelt wird.

Deine "Lösung" ist eben keine, da Du nichts veränderst. Quasi wie 2 +1 - 1 brauch man nicht rechnen, man kann doch gleich bei 2 bleiben ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Hyperion hat geschrieben:Deine "Lösung" ist eben keine, da Du nichts veränderst. Quasi wie 2 +1 - 1 brauch man nicht rechnen, man kann doch gleich bei 2 bleiben ;-)
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.

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. unicode() macht das anscheinend automatisch.

Zu später Stunde noch was gelernt :D
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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:

Code: Alles auswählen

In [188]: u"Hallöle"
Out[188]: u'Hall\x94le'
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)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Um das ganze mal abzuschließen: das Problem war nicht, dass der Parser wahlweise ASCII und Unicode zurückgibt. Das Problem war, dass SQLAlchemy eine Warnung ausgibt, wenn man versucht, einen String in ein Unicode Feld zu schreiben. Es funktioniert zwar trotzdem, ist aber unschön.

Da ich anfangs noch nicht wusste, dass der XML Parser je nach Bedarf String oder Unicode ausspuckt und ich im Wiki als erstes auf .decode() gestoßen bin habe ich eben so angefangen. Zusätzlich haben die ganzen try Blöcke viele Fehler vertuscht und da es sich um über 150 XML Dateien mit teilweise über 12000 Zeilen handelt habe ich zum Testen nur eine Handvoll davon rausgesucht, damit ein Durchlauf nicht so lange dauert. Bedauerlicherweise unterscheiden sich die Dateien wie bereits erwähnt an vielen Stellen und ich hab dadurch den einen oder anderen Fehler erst bemerkt, als ich einen Test über alle Dateien durchgeführt habe. Und so kam halt eins zum anderen.

Jedenfalls funktioniert die aktuelle Version ohne try und ohne Warnungen. Jetzt muss ich noch überprüfen, ob wirklich alles an der richtigen Stelle ist. Bisher hab ich nur Stichproben gemacht
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Antworten