Vorgehen um Zeichensatz-Probleme zu vermeiden?

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.
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Hallo Leute
ich hab mir vorhin die Einträge im Board zu Zeichensatz-Probleme angeschaut, aber nichts gefunden, dass mir wirklich geholfen hätte. Deshalb mal eine Grundsatzfrage:
Wie schaffe ich es Programme zu schreiben, die keinen Tilt kriegen wenn ich aus txt-Files (UTF-8) Daten einlese, die exotischere Zeichen enthalten (von Deutsch, Französisch und Japanisch) diese bearbeiten will (re.findall, replace etc.) und dann wieder in ein txt-File oder eine MySQL Datenbank speichern will?
Wie kann ich ausserdem folgende Fehlermeldung beheben?

Code: Alles auswählen

  File "D:\Python23\lib\codecs.py", line 178, in write
    data, consumed = self.encode(object, self.errors)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 42: ordinal not in range(128)
Sie erscheint, wenn ich die Daten in ein File schreiben will, dass ich als UTF-8 File geöffnet habe.

Für die Hilfe danke ich im voraus!

Grüsse

Clython
hans
User
Beiträge: 728
Registriert: Sonntag 22. September 2002, 08:32
Wohnort: Sauerland
Kontaktdaten:

Unter Linux hat man es da gut. Da ist die QT gleich mit installiert. Bei Windows gibt's da wohl einige Probleme von wegen Lizensierung. Kannst dich aber trotrzdem mal auf www.trolltech.com umsehen

Hans
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Achtung, ich rede hier nicht von der Erstelling von GUIs (dazu ist QT doch da, oder?). Ich rede vom Problem generell! Wie muss ich mich verhalten, um keine Probleme mit dem Zeichensatz zu bekommen?
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Clython,

am Besten für alles, was wirklich Text ist Unicode verwenden im Pythonscript.
Und wenn Du eine Datei erzeugst, das Encoding gleich mit angeben.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding auf Das von deinem Editor verwendete ändern!

import codecs
testtext = u"abcd öäüß €" # wichtig Unicode!
print testtext
f = codecs.open("Test.txt", "wb", encoding="utf-8")
f.write(testtext)
f.close()
siehe auch http://p-nand-q.com/python/unicode_faq.html


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Danke, das war ein guter Tip, ein Problem besteht aber immer noch:
readline() scheint nicht UTF-8 kompatibel zu sein, oder gibt es inzwischen einen Fix für den Bug?
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

hmm wie meinst du dass, readlines ist nicht utf-8 compatibel?

Code: Alles auswählen

import codecs
f = codecs.open("Test.txt", "r", encoding="utf-8")
zeilen = f.readlines()
f.close()
print zeilen # sollten jetzt Unicodestrings sein
Ansonst halt wie in der FAQ beschrieben mit der entsprechenden BOM aus codecs arbeiten.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Was soll dann das?

Code: Alles auswählen

Traceback (most recent call last):
  File "make_wordlist.py", line 75, in ?
    hir_2_wordlist()
  File "make_wordlist.py", line 24, in hir_2_wordlist
    flatten(typ, infile, outfile_flat)
  File "R:\py\Niklaus\modules\hir_to_list.py", line 60, in flatten
    flatten_katalog(infile, outfile)
  File "R:\py\Niklaus\modules\hir_to_list.py", line 42, in flatten_katalog
    zeile = infile.readline()
  File "D:\Python23\lib\codecs.py", line 384, in readline
    return self.reader.readline(size)
  File "D:\Python23\lib\codecs.py", line 295, in readline
    return self.decode(line, self.errors)[0]
UnicodeDecodeError: 'utf8' codec can't decode byte 0xb0 in position 41: unexpected code byte
Das deutet doch eindeutig auf ein Problem mit Unicode hin?
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

das deutet darauf hin, daß du da kein utf-8 hast, 0xb0 ist kein utf-8!
in iso-8859-15 ist das ein ° was als utf-8 mit den beiden Bytes 0xc2 0xb0 codiert wrid.

Code: Alles auswählen

>>> "\xb0".decode("iso-8859-15").encode("utf-8")
Out[6]: '\xc2\xb0'
Hast Du einen Editor, der utf-8 beherrscht und auch das Encoding in Deinem Script gesetzt?


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Ich benutze emacs, der sollte das eigentlich schon können, aber wie kann ich das unter Win überprüfen? Es wird sowieso Zeit, dass ich auf Linux umsteige...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Ich benutze VIM, der Emacs sollte aber auch einen Hex-Modus zum Editieren beherrschen, da kannst Du bei Textdateien leicht nachschaun, ob da dann wirklich Unicode drinsteht oder nicht.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
DER Olf
User
Beiträge: 283
Registriert: Mittwoch 24. Dezember 2003, 19:32

vim gibt es auch für windows :-P

mfg Olf
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Hab nach langer Zeit wieder mal ein bisschen gebastelt, bin aber auf folgendes Problem gestossen:

Code: Alles auswählen

text = replace(text, u" ", u"\n")
Erzeugt bei meinen Dateien keine neue Zeile, sondern löscht nur den Zwischenraum. Woran liegt das?
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Clython,

also bei mir klappts:

Code: Alles auswählen

>>> text = "Hallo Welt!"

>>> print repr(text.replace( u" ", u"\n"))
u'Hallo\nWelt!'

>>> text = u"Hallo Welt!"

>>> print repr(text.replace( u" ", u"\n"))
u'Hallo\nWelt!'

Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Welchen Editor benutzt du? notepad zeigt es nicht korrekt an, andere schon. Haaaargh ich kriege nächstens einen Anfall! Diese Zeichensatzproblematik ist echt mühsam...
NOTZE
User
Beiträge: 106
Registriert: Mittwoch 21. Januar 2004, 20:28

Clython hat geschrieben:Welchen Editor benutzt du? notepad zeigt es nicht korrekt an, andere schon. Haaaargh ich kriege nächstens einen Anfall! Diese Zeichensatzproblematik ist echt mühsam...
Dookie ist vim user.
www.vim.org
gibts auch fuer windows wie Olf schon erwähnte
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Stimmt ich verwende VIM, bei VIM kannst du auch das "fileencoding" einstellen bzw. automatisch für verschiedene Sourcetypen einstellen lassen.
Auch Unicode wird sehr gut unterstützt bei VIM.

Mein Beispiel hab ich in der IPython-Console gemacht, geht in einer normalen Pythonconsole genauso.


Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Mal unabhängig davon, ob mein Editor die Files korrekt anzeigt, hat sich ein neues Problem aufgetan, dessen Ursache (und Lösung) mir nach stundenlangen Recherchen im Netz nicht klar wurde:

Ich habe also diese UTF-8 Files. Wenn ich deren Inhalt in eine mySQL Datenbank einlesen will, kriege ich folgende Fehlermeldung:

Code: Alles auswählen

(Heizen/Kühlen)

Traceback (most recent call last):
  File "sql_processes.py", line 54, in ?
    sql_fill_wortliste()
  File "sql_processes.py", line 29, in sql_fill_wortliste
    sql_write_word(wort, ID, cursor)
  File "sql_processes.py", line 8, in sql_write_word
    output = cursor.execute("""insert into wortliste_d (id, wort, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, vorkommen) values (%s, '%s', %s, %s, %s
, %s, %s, %s, %s, %s, %s, %s, '%s')""" % (ID, word, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, foo))
  File "d:\python23\lib\site-packages\MySQLdb\cursors.py", line 95, in execute
    return self._execute(query, args)
  File "d:\python23\lib\site-packages\MySQLdb\cursors.py", line 114, in _execute
    self.errorhandler(self, exc, value)
  File "d:\python23\lib\site-packages\MySQLdb\connections.py", line 33, in defaulterrorhandler
    raise errorclass, errorvalue
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 107: ordinal not in range(128)
Man muss dabei noch anmerken, dass zum Beispiel das Zeichen ü in emacs als ü angezeigt wird. Das gleiche gilt für alle anderen Umlaute und das Grad (°) Zeichen.

Ändere ich ü in ü usw. (das dann auch in WordpadMFC und emacs so angezeigt wird, wenn ich die Datei abspeichere und neu öffne, erzeugt das Script folgende Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "sql_processes.py", line 54, in ?
    sql_fill_wortliste()
  File "sql_processes.py", line 31, in sql_fill_wortliste
    wort = infile.readline()
  File "d:\python23\lib\codecs.py", line 384, in readline
    return self.reader.readline(size)
  File "d:\python23\lib\codecs.py", line 295, in readline
    return self.decode(line, self.errors)[0]
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 9-14: unsupported Unicode code range 
Wo liegt das Problem? In der Datenbank (die übrigens unter UTF-8 läuft) oder Python. Wie kann ich das Problem beheben?

Quelltext:

Code: Alles auswählen

def sql_write_word(word, ID, cursor):
    foo = "leer"
    output = cursor.execute("""insert into wortliste_d (id, wort, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, vorkommen) values (%s, '%s', %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, '%s')""" % (ID, word, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, foo))
    print output

def sql_fill_wortliste():
    print "Bitte geben Sie Datei an:"
    infile_name = raw_input()
    infile = codecs.open(infile_name, "r", "utf-8")
    ID = 1
    print ID
    wort = infile.readline()
    conn = MySQLdb.connect(db="niklaus", user="mael")
    cursor = conn.cursor()
    while wort:
        sql_write_word(wort, ID, cursor)
        ID = ID + 1
        wort = infile.readline()
        print ID
        print wort
    print "Ende"
    conn.close()
    infile.close()
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Die Datei enthälst im 2. Fall kein UTF-8.

änder mal die Zeile 8 so daß du an den cursor einen Unicodestring übergibst.

Code: Alles auswählen

output = cursor.execute(u"""insert into wortliste_d (id, wort, x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, vorkommen) values (%s, '%s', %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, '%s')""" % (ID, word, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, foo))

Gruß

Dookie
[code]#!/usr/bin/env python
import this[/code]
Patrick
User
Beiträge: 49
Registriert: Montag 5. Juli 2004, 06:35
Wohnort: Berlin
Kontaktdaten:

Bei mir funktioniert das alles nicht.
Ich kann die von einem HTML-Formular empfangenen Strings codieren und decodieren wie ich will, mit welchem Zeichensatz ich will oder was auch immer.
Sobald ich den String in die MySQL-Datenbank schreiben will, heisst es:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf6 in position 0: ordinal not in range(128)
:-(
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Patrick hat geschrieben: Sobald ich den String in die MySQL-Datenbank schreiben will, heisst es:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf6 in position 0: ordinal not in range(128)
Hi Patrick!

Füttere deine Datenbank mit Unicode-Strings. Ob deine Datenbankschnittstelle mit Unicode-Strings arbeitet, das lässt sich sehr einfach herausfinden. Lass dir von der Datenbank ein Feld, das mit Text befüllt ist, zurück geben und prüfe die Variable, in die du den Wert gespeichert hast. type(variablename) --> gibt dir den Objekttype zurück. Wenn dann Unicode raus kommt, dann bekommst du von der Datenbank Unicode-Strings und sollst diese auch mit korrekten Unicode-Strings füttern.

Siehe auch http://www.python-forum.de/viewtopic.php?t=5095

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten