Weil ich Trottel immer "Unicode()" geschrieben habe. Keine Ahnung, wie ich darauf gekommen bin. Ich werd die Tipps auf jeden Fall mal einfließen lassenHyperion hat geschrieben: Wieso wandelst Du nicht immer perCode: Alles auswählen
unicode(value)
lxml: Alternative Fehlerbehandlung für try
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Ok, ich hab jetzt mein Programm umgeschrieben. Das Beispiel vom ersten Beitrag sieht jetzt so aus
Ich habe allerdings ein neues Problem, welches ich mir bisher nichtmal ansatzweise erklären kann. Es ist vorher durch die vielen try Blöcke wohl nicht aufgefallen.
Code: Alles auswählen
for module in modules:
attributes = module.attrib
text=attributes.get("text", default="").decode("utf-8")
implements=attributes.get("implements", default="").decode("utf-8")
name=attributes.get("name", default="").decode("utf-8")
# Create Module
Module = model.modules_module(implements=implements, name=name, text=text)
# Append Module to Device
Device.module.append(Module)Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
Ich hab wohl die Ursache. In den XML Files sind Kommentare, die lxml offensichtlich als reguläre Tags parst
Wenn ich die Kommentare entferne läuft es fehlerfrei durch
Ist das ein Bug oder muss ich da einen anderen Parser verwenden?
[EDIT] Problem gelöst. Ich muss in der Schleife for bitfield in reg: noch ein .xpath("bitfield") anhängen, damit die Kommentare gefiltert werden
Code: Alles auswählen
<reg name="FUSEBYTE4" offset="0x04" size="1" text="Start-up Configuration">
<bitfield mask="0x10" name="RSTDISBL" text="External Reset Disable"/>
<bitfield enum="SUT" mask="0x0C" name="SUT" text="Start-up Time"/>
<bitfield mask="0x02" name="WDLOCK" text="Watchdog Timer Lock"/>
<!--bitfield name="JTAGEN" mask="0x01" text="JTAG Interface Enable"/-->
</reg>Ist das ein Bug oder muss ich da einen anderen Parser verwenden?
[EDIT] Problem gelöst. Ich muss in der Schleife for bitfield in reg: noch ein .xpath("bitfield") anhängen, damit die Kommentare gefiltert werden
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Den Code könnte man einfacher und flexibler schreiben:
Das decodieren ist doch unnötig, wie wir ja nun wissen (denn in Deiner Module-Klasse wird das eh implizit konvertiert); zudem liegt ja nicht mal "utf-8" vor, sondern nur "ascii". (Ok, "ascii" ist eine Untermenge von "utf-8", dennoch emfpinde ich das als verwirrend)
Vor allem kannst Du daraus eine universelle Funktion basteln, die Dir basierend auf einer key-Liste ein neues Dictionary erstellt, welches die gewünschten Daten enthält.
Man könnte statt einer Liste sogar ein initiales Dictionary bauen und für jeden key ggf. noch eine Funktion angeben, die für die Umwandlung von solchen Sonderfällen (wie vorhin von Dir beschrieben) aufgerufen werden soll.
Code: Alles auswählen
keys = ["name", "implements", "text"]
for module in modules:
attributes = dict(zip(keys, map(module.attrib.get, keys)))
# Create Module
my_module = model.modules_module(**attributes)
# Append Module to Device
Device.module.append(my_module)
Vor allem kannst Du daraus eine universelle Funktion basteln, die Dir basierend auf einer key-Liste ein neues Dictionary erstellt, welches die gewünschten Daten enthält.
Man könnte statt einer Liste sogar ein initiales Dictionary bauen und für jeden key ggf. noch eine Funktion angeben, die für die Umwandlung von solchen Sonderfällen (wie vorhin von Dir beschrieben) aufgerufen werden soll.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Wie ich schon erwähnt habe sind auch Zahlen enthalten. Das sieht dann so aus
Die Funktion attr2int() wandelt alle vorkommenden Stringvarianten in einen Integer oder None um. An der Stelle komme ich mit deiner Methode leider nicht weiter, sonst hätte ich das schon so gemacht. Ich müsste für jeden Key dann noch hinterlegen, ob es ein String oder Integer werden soll.
Das Dekodieren wäre nicht nötig, aber ich will durchgängig mit utf-8 arbeiten. Wenn ich aber einen <str> der Datenbank übergebe bekomme ich immer Warnungen
Code: Alles auswählen
# Get Reg from Registers
for reg in list(temp):
attributes = reg.attrib
size = attr2int(attributes.get("size"))
name = attributes.get("name", default = "").decode("utf-8")
text = attributes.get("text", default = "").decode("utf-8")
offset = attr2int(attributes.get("offset"))Das Dekodieren wäre nicht nötig, aber ich will durchgängig mit utf-8 arbeiten. Wenn ich aber einen <str> der Datenbank übergebe bekomme ich immer Warnungen
Code: Alles auswählen
/usr/local/lib/python2.6/dist-packages/SQLAlchemy-0.6.5-py2.6.egg/sqlalchemy/engine/default.py:506: SAWarning: Unicode type received non-unicode bind param value.
param.append(processors[key](compiled_params[key]))
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Ok, dann schlage ich diesen Ansatz vor:
Auf diese Weise hast Du eine hohe Flexibilität und hältst Dich auch an DRY.
Code: Alles auswählen
attributes = {
"size": attr2int
"name": unicode,
"text": unicode,
"offset": attr2int
}
for module in modules:
params = {}
for name, func in attributes:
try:
params[name] = func(module.attrib[name])
except KeyError:
pass
# Create Module
my_module = model.modules_module(**params)
# Append Module to Device
Device.module.append(my_module)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ah, interessanter Ansatz. Danke. Ich knabbere gerade an einem anderen Problem. In den XML Files sind teilweise solche Codes enthalten µ und lxml scheint die zu interpretieren. Dann geht die Unicode Konvertierung in die Binsen.
Wenn ich das gelöst habe schau ich mir das mal an
Wenn ich das gelöst habe schau ich mir das mal an
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Also ich habe da keine Probleme:burli hat geschrieben:Ich knabbere gerade an einem anderen Problem. In den XML Files sind teilweise solche Codes enthalten µ und lxml scheint die zu interpretieren. Dann geht die Unicode Konvertierung in die Binsen.
Code: Alles auswählen
In [174]: xml = u"""<test>Zeichen: µ</test>"""
In [175]: root = etree.fromstring(xml)
In [176]: print root.text
--------> print(root.text)
Zeichen: µ
In [177]: print type(root.text)
--------> print(type(root.text))
<type 'unicode'>
In [178]: print unicode(root.text)
--------> print(unicode(root.text))
Zeichen: µ
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
Ok, die Lösung für das Problem ist etwas rabiat, aber funktioniert
Code: Alles auswählen
text=attributes.get("text", default = "").encode("utf-8").decode("utf-8")Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Hu? Das kann keine Lösung sein!burli hat geschrieben:Ok, die Lösung für das Problem ist etwas rabiat, aber funktioniertCode: Alles auswählen
text=attributes.get("text", default = "").encode("utf-8").decode("utf-8")
Code: Alles auswählen
text = attributes.get("text", default = "").encode("utf-8").decode("utf-8")
# ist identisch zu:
text = attributes.get("text", default = "")
# sofern das ein Unicode-Objekt beinhaltet, ansonsten geh auf Nummer sicher:
text = unicode(attributes.get("text", default = ""))
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
& steht aber nicht drinHyperion hat geschrieben: Also ich habe da keine Probleme:
Code: Alles auswählen
<enumerator name="PA_BUF_LT_bitf">
<enum val="0" text="0 µs" constname="PA_BUF_LT_0US"/>
<enum val="1" text="2 µs" constname="PA_BUF_LT_2US"/>
<enum val="2" text="4 µs" constname="PA_BUF_LT_4US"/>
<enum val="3" text="6 µs" constname="PA_BUF_LT_6US"/>
</enumerator>unicode() scheint aber auch zu funktionieren<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
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
- 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
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
assert encoding_kapiert
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 StringsHyperion 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
Code: Alles auswählen
<type 'str'> RX_AACK_ON
<type 'str'> TX_ARET_ON
<type 'str'> 0 µs
<type 'str'> 2 µsAber 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
Das schwierigste beim Programmieren ist, sinnvolle Variablen- und Funktionsnamen zu finden :lol:
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Fast richtig, denn genau das ist doch das "2 + 1 - 1"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 StringsDarauf nochmal .decode("utf-8") und alles passt.Code: Alles auswählen
<type 'str'> RX_AACK_ON <type 'str'> TX_ARET_ON <type 'str'> 0 µs <type 'str'> 2 µs
Eben! Da lag wohl Dein Problem. Dein Vorgehen war beim Auftreten des Fehlers wohl so: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.
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'
Code: Alles auswählen
In [188]: u"Hallöle"
Out[188]: u'Hall\x94le'
Jein. unicode() ist ja als Basisfunktion dokumentiert. Bei einem Unicode-Objekt liefert unicode exakt dasselbe Objekt zurück:burli hat geschrieben: unicode() macht das anscheinend automatisch.
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
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
assert encoding_kapiert
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
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:
