Seite 1 von 1
Problem mit Unicode... ;)
Verfasst: Dienstag 23. Januar 2007, 15:00
von EnTeQuAk
und schon wieder bastel ich ein wenig herum
Habe nun ein Problem mit Unicode...
Ich möchte gerne eine Datei einlesen und mithilfe von blackbirds Tekisuto Parsen.
So alles ansich kein Problem...
Ich habe aber ein Problem mit den Dateien, die ich einlesen möchte.
In welchem Encoding die gespeichert sind, weiß ich nicht. (wird leider auch in der praxis später so sein).
Nun möchte ich die in Unicode umwandeln (benötigt Tekisuto, zum arbeiten...

).
Ich habe das so versucht:
Aber ich bekomme im Enddefekt folgenden Fehler:
Code: Alles auswählen
Traceback (most recent call last):
File "dauCMS.py", line 156, in ?
main()
File "dauCMS.py", line 137, in main
dau_parser.parse_files()
File "parser.py", line 190, in parse_files
for token in self.lexer(u''.join(r_data)):
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
Der Relevante Teil im Code schaut so aus:
Code: Alles auswählen
# Inhalt einlesen
r_data = open(self.project_path+data_file, 'r').read()
try:
# Inhalt parsen
data = ''
for token in self.lexer(u''.join(r_data)):
data += token.data
Mache ich etwas grundsätzlich falsch oder schaue ich nur falsch?
MfG EnTeQuAk
Verfasst: Dienstag 23. Januar 2007, 15:47
von sape
r_data = open(self.project_path+data_file, 'r').read()
Warum machst du das so? Wie soll die Datei jemals geschlossen werden? Nur wenn das Programm beendet wird, würde die Datei bei deiner Methode geschlossen werden.
So, wäre es besser:
Code: Alles auswählen
f = open(self.project_path+data_file, 'r')
try:
# Inhalt parsen
r_data = f.read()
data = ''
for token in self.lexer(u''.join(r_data)):
data += token.data
# An irgendeiner stelle in dieser Funktion explizit die Datei schließen!
f.close()
Zu deinem Problem: Kann dein ``self.lexer`` mit Unicode umgehen? Gibt es da stellen wo du z.B. mit ``str`` umwandelst (Ja kling jetzt eigenartig, ich weiß ^^)
Das...
...ergibt das...
Code: Alles auswählen
str2 = str(str_)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
...weil ``str`` z.B. keine ``Unicode``-Objekte nach ``str``-Objekte umwandel kann.
Es könnte daher sein, dass irgendwelche Funktionen von dir etwas mit ``Unicode`` Strings machen, was die eben nicht können.
lg
P.S.: Gib mal bitte den Link zu der Datei zu deinem SVN-Repos. Möchte mir mal gerne die Methode anschauen.
Verfasst: Dienstag 23. Januar 2007, 16:28
von EnTeQuAk
Danke schonmal für die Tipps.
P.S.: Gib mal bitte den Link zu der Datei zu deinem SVN-Repos. Möchte mir mal gerne die Methode anschauen.
lexer.py
parser.py
lexer.py ist die Datei, die die Syntaxen definiert. Eigentlich nichts besonderes.
parser.py ist die Datei, die dann den gesamten Ablauf von
dauCMS abarbeitet. Hier sind eigentlich erst die Zeilen ab
Zeile 187 wichtig.
MfG EnTeQuAk
Verfasst: Dienstag 23. Januar 2007, 17:09
von sape
Wieso ist die ``dauCMS.py`` noch nicht angepasst?
http://daucms.de/trac/browser/dauCMS/tr ... r=name#L65
Code: Alles auswählen
dau_parser = MainParser(
syntax_list = syntax_list,
project = opts['project'],
template = opts['template'],
)
Der Konstruktor von ``MainParser`` in ``parser.py`` sieht aber so aus:
Code: Alles auswählen
class MainParser:
def __init__(self, project, template, lexer):
Das ``keyword`` syntax_list gibt es also nicht im Konstruktor.
Ich würde gerne wissen was an den Parameter ``lexer`` übergeben wird (wir ja im self.lexer gespeichert). Wenn ich das erstmal weiß kann ich mir die Funktion/Klasse,was auch immer, anschauen (=Link).
Aber wie gesagt, ``dauCMS.py`` scheint irgendwie nicht auf den aktuellsten Stand zu sein, wegen dem oben genanten.
BTW: Irgendwas ist mit euren Server los. Der hat aussetzter.
lg
Verfasst: Dienstag 23. Januar 2007, 17:47
von EnTeQuAk
Hoppla... vergessen zu sagem.
Immo arbeiten wir noch mit einem eigenen Lexer und Parser... und sind eben dabei mit Tekisuto rumzuspielen.
Die richtige Adresse, für die "aktuellen" spiel-dateien ist
http://daucms.de/trac/browser/dauCMS/tr ... order=name
Alles, was darüber ist, hat nichts mit diesem Thread zu tun
"BTW: Irgendwas ist mit euren Server los. Der hat aussetzter. "
ja, ja, ja

das höre ich auch vom Team

-- das liegt entweder an mod_python + Trac oder nur an Trac... aber das ist erstmal nebensächlich
MfG EnTeQuAk
Verfasst: Dienstag 23. Januar 2007, 18:15
von sape
Thx. Das sieht schon aktueller aus

Ich stöbere mal ein wenig darum, da ich gerade Zeit und Lust habe. Mal schauen, vielleicht finde ich da den Fehler.
lg
Verfasst: Dienstag 23. Januar 2007, 18:20
von EnTeQuAk
Thx. Das sieht schon aktueller aus Very Happy Ich stöbere mal ein wenig darum, da ich gerade Zeit und Lust habe. Mal schauen, vielleicht finde ich da den Fehler.
Wunderbar... ich tue das auch schon seit einigen Stunden

Bisher hab ich noch nichts richtiges gefunden.
Würde mich sehr freuen.
MfG EnTeQuAK
Verfasst: Dienstag 23. Januar 2007, 18:30
von sape
OK, allso ist der ``self.lexer``, der am Konstruktor von
MainParser übergeben wird,
``DAUSyntax`` der eine Spezialisierung von ``BaseLexer`` in
``tekisuto.lexer.py`` ist.
...
So, das hätte ich mir aber auch sparen können weil ich den Fehler gefunden habe
Schau mal hier:
Code: Alles auswählen
str2 = u"".join(str_)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Hier wird versucht ein ``join`` zumachen auf einen string der nicht Unicode ist, dessen Ergebnis aber Unicode sein muss (u"".) - (Ich hoffe man kann es einigermaßen verstehen)
Die Lösung sieht so aus:
Das heißt, lese deine Datei im Unicode Modus ein, oder wandele das eingelesen in ein ``unicode``-Objkt um
Ich hoffe ich konnte helfen.
lg
sape
Verfasst: Dienstag 23. Januar 2007, 19:05
von EnTeQuAk
Das heißt, lese deine Datei im Unicode Modus ein, oder wandele das eingelesen in ein ``unicode``-Objkt um Smile
Hmm...
mit dem umwandeln meinst du doch sicherlich:
oda?
Das jedenfalls geht nicht.
Code: Alles auswählen
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Und was meinst du mit als Unicode einlesen? -- Wie mache ich das?
Habe schon in der Doku gelesen, bei den methoden 'file()' und 'open()' aber direkt etwas gefunden.
Ich probiere gerade verschiedene Sachen mit der methode 'unicode()' aus... vllt. werde ich da fündig.
Danke auf jedenfall schonmal!
MfG EnTeQuAK
Verfasst: Dienstag 23. Januar 2007, 19:28
von sape
Puh, bin nicht der Experte mit Unicode.
Ich habe das damals so gemacht:
Code: Alles auswählen
import codecs
f = codecs.open("c:\foobar.txt", "iso-8859-1")
Hab einfach die Dateien in "iso-8859-1" eingelesen.
lg
P.S.: Warte aber mal ab ob nicht jemand ne bessere Lösung hat. Vielleicht mal Birkenfeld oer BlackBird fragen wie die das mit dem Unicode sauber lössen (Irgendwas haben die sich bestimmt dafür gebaut)
BTW: Würde ich auch gerne wissen
lg
Verfasst: Dienstag 23. Januar 2007, 19:31
von sape
EnTeQuAk hat geschrieben:
mit dem umwandeln meinst du doch sicherlich:
oda?
Ne, das geht ja leider nicht (Weis auch nicht warum)
Ich meinte das so:
EDIT:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, codecs
stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()
str_ = "üöß"
str2 = str_.decode('utf-8')
print str2.encode(stdout_encoding) # -> üöß
Verfasst: Dienstag 23. Januar 2007, 19:35
von EnTeQuAk
So... erweiternd dazu

Das Wiki... Ach ja... schön, das es das Gibt
[wiki]Von Umlauten, Unicode und Encodings[/wiki]
Da steht auch noch einiges drinne, was sehr interessant ist.
Bin aber trotzdem auf die anderen gespannt
MfG EnTeQuAk
EDIT:
gerade deinen 'EDIT' gesehen

-- auch interessant. Werde mal alles nach und nach ausprobieren.
Verfasst: Dienstag 23. Januar 2007, 19:37
von sape
EnTeQuAk hat geschrieben:So... erweiternd dazu

Das Wiki... Ach ja... schön, das es das Gibt
Jepp, von daher habe ich das auch

Re: Problem mit Unicode... ;)
Verfasst: Dienstag 23. Januar 2007, 19:45
von gerold
EnTeQuAk hat geschrieben:Habe nun ein Problem mit Unicode...
Hi EnTeQuAk!
http://www.python-forum.de/post-30572.html ...falls du es noch nicht kennst.
Das ist auch evt. nützlich, auch wenn es für ein spezielles Excel-Problem geschrieben wurde:
http://www.python-forum.de/post-54734.html#54734
Diese beiden Links sollen dich generell über die Unicode-Problematik aufklären.
Es ist also zuerst mal wichtig, herauszufinden in welchem Coding der Quell-String vorhanden ist. -- Auch wenn man teilweise nur raten kann, aber raten ist immer noch besser als gar nichts tun.
Sobald das Quell-Encoding bekannt ist, ist es kein Problem mehr, nach Unicode umzuwandeln.
Folgende Encodings sind für den deutschsprachigen Raum interessant:
- iso-8859-1
- iso-8859-15
- mbcs
- cp850
- cp1252
Dann noch UTF-8 als Universal-Coding.
mfg
Gerold

Verfasst: Dienstag 23. Januar 2007, 21:03
von EnTeQuAk
Das ist verdammt interessant.
Ich habe nun folgendes eingefügt:
Code: Alles auswählen
# Inhalt einlesen
r_data = open(self.project_path+data_file, 'r').read()
if not isinstance(r_data, unicode):
r_data = r_data.decode('iso-8859-1')
else:
print 'nöööö'
Damit klappt das schonmal ein wenig weiter.
Nun bekomme ich einen weiteren Fehler in folgendem Code:
Code: Alles auswählen
try:
# geparsten Inhalt nach self.rendered_project_name schreiben
# FIXME: " data_file[:4] " -- it's not realy a good resolution...
# it's stupid if 'data_file' doesn't end with '.txt'
to_write = open(self.rendered_project_path+data_file[:-4]+'.html', 'w')
to_write.write(tmp_to_write)
to_write.close()
except Exception, e:
raise ParserError('Error while writing file %s ' % data_file, e )
Der Fehler ist folgender:
(ein wenig durch eigene Fehlerklasse formatiert)
Code: Alles auswählen
parser.ParserError:
An error is ocured:
Error while writing file dokumentation.txt
'ascii' codec can't encode character u'\xe4' in position 970: ordinal not in range(128)
Um nachzuvollzieren, wo 'tmp_to_write' herkommt:
Code: Alles auswählen
if self.template_to_render == None:
tmp_to_write = data
else:
tmp_to_write = open('%s/templates/%s/%s.html' %(sys.path[0],\
self.template_to_render,\
self.template_to_render),'r').read()
So. Muss ich dort auch noch das Coding beachten?
Ein weiteres
Code: Alles auswählen
if isinstance(r_data, str):
tmp_to_write = tmp_to_write.decode('iso-8859-1')
Für Weitere Informationen:
http://daucms.de/trac/browser/dauCMS/tr ... order=name
mfG EnTeQuAk
Verfasst: Dienstag 23. Januar 2007, 21:26
von gerold
EnTeQuAk hat geschrieben:Code: Alles auswählen
# Inhalt einlesen
r_data = open(self.project_path+data_file, 'r').read()
if not isinstance(r_data, unicode):
r_data = r_data.decode('iso-8859-1')
else:
print 'nöööö'
Hi EnTeQuAk!
Ich lese gar nicht weiter, dann hier liegt schon mal ein Fehler vor.
Wenn du mit ``open`` oder mit ``file`` eine Textdatei öffnest und einliest, dann hast du kein Unicode. Du hast einen Bytestring in irgendeiner Codierung. Welche das ist, hängt primär vom verwendeten Betriebssystem und von der Ländereinstellung ab. Unter einem deutschsprachigen Windows wird das wohl "cp1252" sein. Unter einem deutschsprachigen Linux meistens "iso-8859-1(5)" oder "UTF-8". Ein paar Dateien sind unter Windows auch UTF-16-codiert, aber die sind eher selten.
Du brauchst also nicht prüfen, ob du Unicode raus bekommst, denn da kommt kein Unicode raus. Unicode wird nur intern verwendet.
Versuche also erst mal das bevorzugte Encoding raus zu bekommen:
Dann würde ich versuchen, mit Hilfe dieses bevorzugten Encodings, den Bytestring nach Unicode umzuwandeln:
Code: Alles auswählen
>>> f = file("J://Ablage//irgendeinedatei.txt", "r")
>>> bytestring = f.read()
>>> unicodestring = f.read().decode(locale.getpreferredencoding())
>>> f.close()
>>>
Erst wenn es dabei einen Fehler gibt, dann würde ich dem Benutzer ein paar Encodings in einer Combobox zur Auswahl präsentieren. Diese Auswahl würde ich in einer INI-Datei speichern und beim nächsten Mal zuerst das gespeicherte Encoding ausprobieren -- dann erst das ``preferredencoding``.
mfg
Gerold

Verfasst: Dienstag 23. Januar 2007, 21:40
von gerold
...das hätte ich fast vergessen.
Wenn du einen UNICODE-String hast und du möchtest diesen in eine Textdatei, mit dem für das Betriebssystem und dessen Ländereinstellung üblichen Encoding schreiben, dann bist du mit dem ``codecs``-Modul bestens bedient.
Code: Alles auswählen
>>> import codecs
>>> import locale
>>> f = codecs.open("J://Ablage//irgendeinedatei.txt", mode='w', encoding = locale.getpreferredencoding())
>>> f.write(u"löüäßßßß") # hier wissen wir genau, dass es ein UNICODE-String ist. :-)
>>> f.close()
>>>
mfg
Gerold
