Von Python, Umlauten, Unicode und Encodings

Gute Links und Tutorials könnt ihr hier posten.
Antworten
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 1. Februar 2006, 15:11

Von Python, Umlauten, Unicode und Encodings

Immer wieder tauchen Fragen zu Umlauten und Unicode auf. Mit dieser kurzen Anleitung versuche ich dieses Thema so einfach wie möglich zu erklären. Dabei geht es mir nicht um die korrekte Darstellung von dem was wirklich im Hintergrund passiert.


Umlaute im Python-Code

Python verwendet zwei verschiedene Objekttypen zum Speichern von Text. --> str und unicode.

Wenn man Python keine besonderen Anweisungen gibt, dann wird Text, den man einfach nur in Anführungszeichen schreibt, als Objekt vom Typ str abgespeichert (s = "Hallo Welt"). Dieser Typ kann normalerweise nur mit den Zeichen etwas anfangen, die auch im amerikanischen Englisch Gebrauch finden. Da es in der englischen Sprache keine Umlaute wie Ö oder Ä gibt, können diese, ohne besondere Vorkehrungen, nicht in ein Objekt
vom Typ str geschrieben werden.

Um trotzdem Umlaute verwenden zu können, hat man etwas eingeführt, das Python anzeigt in welchem Encoding das Python-Modul geschrieben wurde. Mit Hilfe eines Encoding Cookies zeigt man Python das Encoding des Python-Modules.

So könnte ein solches Cookie aussehen.

Code: Alles auswählen

# -*- coding: iso-8859-1 -*-
Dieses Encoding Cookie muss in der ersten oder zweiten Zeile im Modul stehen. Wichtig dabei ist allerdings, dass in diesem Encoding Cookie auch wirklich das Encoding angegeben wird, in dem die Datei abgespeichert wird. Es funktioniert nicht, wenn man dem Python-Interpreter mit # -*- coding: utf-8 -*- signalisiert, dass die Datei im UTF-8-Encoding abgespeichert wurde, wenn in Wirklichkeit die Datei als ISO-8895-1-Datei abgespeichert wird.

Viele einfache Editoren lassen einem keine Wahl -- besonders unter Windows ist das gerne der Fall. Wenn in einem deutschsprachigen Windows im Editor keine Auswahl getroffen werden kann, dann ist man mit dem Encoding Cookie # -*- coding: iso-8859-1 -*- nicht schlecht bedient. Eigentlich wäre das Encoding von Windows cp1252, aber darauf müssen wir hier nicht genauer eingehen.

Unter Linux können viele Editoren mit verschiedenen Encodings umgehen. Wenn man keine Auswahl trifft, dann wird die Datei im Standard-Encoding abgespeichert. Dieses Standard-Encoding findet man heraus, wenn man in einer Kommandozeilen-Konsole (Shell) den Befehl /usr/bin/locale eingibt:

Code: Alles auswählen

de_DE       -->  # -*- coding: iso-8859-1 -*-
de_DE@euro  -->  # -*- coding: iso-8859-15 -*-
de_DE.utf8  -->  # -*- coding: utf-8 -*-

de_AT       -->  # -*- coding: iso-8859-1 -*-
de_AT@euro  -->  # -*- coding: iso-8859-15 -*-
de_AT.utf8  -->  # -*- coding: utf-8 -*-
Ab dem Moment, in dem das Encoding definiert wurde, können auch Umlaute und andere Sonderzeichen, die vom definierten Encoding abgedeckt werden, als String und in den Kommentaren Verwendung finden.

Vor der Definition des Encodings hätte Python eine Warnung angezeigt wenn man einen String mit Umlauten eingegeben hätte:

Code: Alles auswählen

s = "Hallo Welt" # OK
s = "Hallo Österreich" # Fehler/Warnung
Nach der Definition des Encodings:

Code: Alles auswählen

s = "Hallo Welt" # OK
s = "Hallo Österreich" # OK

Umwandeln zwischen den verschiedenen Encodings

Python verwendet als Basis Unicode! So kurz dieser Satz auch ist, so wichtig ist er. Möchte man einen Text von einem Encoding in ein anderes Umwandeln, dann geschieht das in zwei Schritten.

Code: Alles auswählen

iso-8859-1  -->  Unicode  -->  utf-8
utf-8       -->  Unicode  -->  iso-8859-1
...
Die Umwandlung nach Unicode wird von decode() und die Umwandlung von Unicode in ein anderes Encoding wird von encode() erledigt.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

# Text definieren
s_iso88591 = "Hallo Österreich"

# Text nach Unicode umwandeln
s_unicode = s_iso88591.decode("iso-8859-1")

# Text nach UTF-8 umwandeln
s_utf8 = s_unicode.encode("utf-8")

print type(s_iso88591)
print type(s_unicode)
print type(s_utf8)

try:
    print s_iso88591
except:
    print "Nicht darstellbar..."

try:
    print s_unicode
except:
    print "Nicht darstellbar..."

try:
    print s_utf8
except:
    print "Nicht darstellbar..."
Aus diesem Beispiel lassen sich schon ein paar Dinge herauslesen.

- Wird das Encoding in einem Encoding Cookie angegeben, dann weiß Python,
mit welchem Encoding die Datei abgespeichert wurde und kann den Code
beim Interpretieren entsprechend umwandeln.

- Man muss beim Umwandeln nach Unicode, das Quell-Coding angeben.

- Man muss beim Umwandeln von Unicode, das Ziel-Coding angeben.

- Der Typ des Objektes sagt nichts über das verwendetet Encoding aus.

- Manche Encodings sind nicht in einer Konsole (Shell) darstellbar.
Welche Encodings funktionieren, ist abhängig vom Betriebssystem und den
Einstellungen der jeweiligen Konsole mit der das Programm gestartet
wurde. (Deshalb wurden die Print-Anweisungen in try und except
eingeschlossen.)

Man kann sich einen Arbeitsschritt sparen, wenn der Text direkt im Modul geschrieben wird. Man kann schon beim Definieren der Variable den Text nach Unicode umwandeln. Das sieht so aus:

Code: Alles auswählen

s_unicode = u"Hallo Österreich"
Man erspart sich in unserem Fall die Umwandlung von iso-8859-1 nach Unicode. Durch das Encoding Cookie weiß Python, dass der String innerhalb der Anführungszeichen iso-8859-1 ist und kann deshalb ohne Angabe des Quell-Codings nach Unicode umwandeln. Es muss vor den Anführungszeichen einfach nur ein u geschrieben werden.


Umlaute in die Konsole schreiben (print)

Python läuft unter den verschiedensten Betriebssystemen. Deshalb ist es ein wenig schwieriger, sich auf ein einheitliches Encoding für die Kommandozeile zu einigen. Es läuft derzeit ein großer Umbruch von den verschiedenen Encodings, hin zu UTF-8. Mit UTF-8 als gemeinsames Encoding gäbe es keine Probleme mit den Umlauten. Leider kann das noch Jahre dauern, bis alle Betriebssysteme dieser Welt UTF-8 als Standard-Encoding verwenden.

Bis es so weit ist, müssen wir beim Programmieren auf dieses Thema eingehen und uns selbst darum kümmern, dass der Text den wir an die Konsole schicken, einem Encoding entspricht mit dem die Konsole etwas anfangen kann. Mit Konsole meine ich die Dos-Eingabeaufforderung sowie die verschiedensten Shells die man unter den anderen gängigen Betriebssystemen so verwendet.

Das Encoding der Standardausgabe (STDOUT) kann man so abfragen:

Code: Alles auswählen

stdout_encoding = sys.stdout.encoding
Das funktioniert aber nicht, wenn man ein Skript in einigen der üblichen IDEs startet, da diese meist STDOUT umleiten, so dass die Ausgabe innerhalb der IDE angezeigt wird. Das kann man meist so umgehen:

Code: Alles auswählen

stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()
Wenn man einen Text mit Umlauten an die Konsole (in unserem Fall STDOUT) schicken möchte, dann muss man diesen Text in das Encoding der Konsole umwandeln. Wie ich bereits weiter oben schon beschrieben habe, muss
diese Umwandlung über Unicode laufen. Hier ein Beispiel:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import sys

# Encoding der Standardausgabe herausfinden
stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()

# Nachricht definieren (durch das Encoding Cookie als iso-8859-1 gekennzeichnet)
message = "Hallo Österreich"

# Nachricht umwandeln (iso-8859-1 -> unicode -> Ausgabe-Encoding) und
# mit print an die Standardausgabe übergeben.
print message.decode("iso-8859-1").encode(stdout_encoding)
Das gleiche Beispiel ein wenig kürzer (es entfällt die Umwandlung nach Unicode):

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import sys

# Encoding der Standardausgabe herausfinden
stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()

# Nachricht definieren (durch das Encoding Cookie als iso-8859-1 gekennzeichnet)
message = u"Hallo Österreich"

# Nachricht umwandeln (unicode -> Ausgabe-Encoding) und
# mit print an die Standardausgabe übergeben.
print message.encode(stdout_encoding)

Umlaute von der Kommandozeile übernehmen

Wenn ein Programm über die Kommandozeile gestartet wird, dann kann man Parameter an das Programm übergeben. Diese können mit sys.argv abgefragt und verwendet werden.

Solch ein Aufruf könnte so aussehen:

Code: Alles auswählen

python mein_skript.py "Hallo Österreich" "Über den Wolken"
Um mit diesen Argumenten etwas anfangen zu können, muss man den Text vom Encoding der Kommandozeile nach Unicode oder in das Encoding des Python-Skriptes umwandeln.

VORSICHT! Das Encoding der Kommandozeile ist nicht das Encoding von STDIN.

Das Encoding der Kommandozeile lässt sich mit sys.getfilesystemencoding() feststellen. Es ist also das Encoding, mit dem die Dateinamen der Dateien gespeichert werden.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import sys

# Encoding der Standardausgabe und des Dateisystems herausfinden
stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()
fs_encoding = sys.getfilesystemencoding()

# Kompletten Kommandozeilenaufruf übernehmen und nach Unicode umwandeln
cmd_original = " ".join(sys.argv)
cmd_unicode = cmd_original.decode(fs_encoding)

# String verändern und wieder an die Kommandozeile übergeben
cmd_unicode += u" (öäü)"
print cmd_unicode.encode(stdout_encoding)

Umlaute von Datenbanken oder Dateien

Die String-Daten, die man aus einer Datenbank liest, sind ziemlich sicher nicht im gleichen Encoding wie unser Skript. (durch Encoding Cookie definiert)

Meist kümmert sich die Schnittstelle darum, dass die Daten von der Datenbank nach Unicode umgewandelt werden. Das lässt sich leicht feststellen, indem man mit type() einen der Strings aus der Datenbank überprüft. Das hat den Vorteil, dass man weiß woran man ist und nicht mehr nach Unicode umwandeln muß, um zum gewünschten Ziel-Encoding zu gelangen.

Ist das nicht der Fall, muss man erst einmal feststellen, in welchem Encoding die Werte an das Python-Programm übergeben werden. Vielleicht gibt es einen Hinweis in der Beschreibung der Datenbank oder der Datenbankschnittstelle. Aber auch mit "Try and Error" lässt sich herausfinden, welches Encoding von der Datenbank verwendet wird. Hat man das Encoding herausgefunden, dann sollte man sich im Programm darum kümmern, dass die Strings vor der Verwendung nach Unicode oder in das Encoding des Skriptes umgewandelt werden.

Alles hier geschriebene gilt natürlich auch in umgekehrter Reihenfolge. Beim Schreiben in die Datenbank muss man sich natürlich auch darum kümmern, dass das richtige Encoding verwendet wird. Auch hier ist es wieder am Einfachsten, wenn sich bereits die Datenbankschnittstelle darum kümmert und man einfach mit Unicode arbeiten kann.


Lesen und Schreiben von Dateien

Normalerweise braucht man sich nicht um das Encoding der Dateien zu kümmern. Meist liest man die Datei mit dem gleichen Betriebssystem, mit dem die Datei geschrieben wurde.

Natürlich gibt es Ausnahmen und für solche Fälle gibt es das Modul codecs. Damit lassen sich Dateien mit den verschiedensten Encodings öffnen, lesen und schreiben. Man kann mit dem Befehl codecs.open() eine Datei öffnen und dabei gleich auch noch das Encoding angeben, mit dem in die Datei geschrieben wird.

Wird beim Schreiben in diese Datei ein Unicode-String übergeben, dann wird dieser automatisch in das vorher definierte Ziel-Encoding umgewandelt.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import sys
import codecs

# Encoding der Standardausgabe herausfinden
stdout_encoding = sys.stdout.encoding or sys.getfilesystemencoding()

# Datei schreiben
f = codecs.open("dateiname.txt", "w", "utf-8")
message = u"Über den Wolken"
f.write(message)
f.close()

# Datei lesen
f = codecs.open("dateiname.txt", "r", "utf-8")
s_unicode = f.read()
f.close()

# In die Konsole schreiben
print s_unicode.encode(stdout_encoding)

----

2006-02-01, gerold.penz@tirol.utanet.at

Falls ich beim Umwandeln nach BBcode einen Fehler gemacht habe --> füge ich noch den Originaltext bei, den ich in reStructuredText geschrieben habe.

http://paste.pocoo.org/show/750/ (veraltet)

Edit: reStructuredText ausgelagert.
Zuletzt geändert von gerold am Donnerstag 22. März 2007, 20:11, insgesamt 6-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 1. Februar 2006, 15:21

Super Text!

Wäre eigentlich ideal für das Wiki... Aber du magst es nicht, was?

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 1. Februar 2006, 21:40

jens hat geschrieben:Super Text!
Wäre eigentlich ideal für das Wiki... Aber du magst es nicht, was?
Hi Jens!

Danke. Aber du hast Recht -- Ich mag das Wiki immer weniger. Alleine, wenn ich mir den Verlauf (info) der Seite [wiki]Python im Web[/wiki]ansehe... Mit jeder neuen Version der Seite wurden immer mehr Infos unterschlagen und nur mehr für WSGI-Werbung benutzt. Wenn ich die Infos der alten Seite http://www.pythonwiki.de/PythonWeb irgendwo unterbringen möchte, dann müsste ich alles komplett umschreiben. Ich lasse euch das Wiki als Spielwiese und hoffe nur, dass die Einträge des alten Wiki erhalten bleiben. CGI ist nicht tot und viele, die von PHP kommen, wünschen sich so etwas wie Servlets http://nick.gerf.org/pse/examples/tutorial.html oder Snakelets http://snakelets.sourceforge.net/manual/ypage.html.
Aber davon steht nichts im Wiki und ich weiß nicht wo ich das dazuschreiben sollte.

lg
Gerold
:-)

PS: Wenn diese Anleitung nicht grob bemängelt wird, dann bitte ich dich, den reStructuredText zu nehmen und im Wiki an einem geeigneten Ort unter zu bringen. Ich kann ja nicht einfach in der Wiki-Hauptseite einen Eintrag für diese Anleitung machen. Also weiß ich auch in diesem Fall nicht wohin damit.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
jens
Moderator
Beiträge: 8482
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Mittwoch 1. Februar 2006, 22:16

Aber da sprichst du einen Punkt an, der wichtig ist und geklärt werden sollte. Ich denke auch, das das Wiki noch einige Strukturen braucht, siehe: [wiki]Diskussion/Übersicht#PythonwikiPdfStruktur[/wiki]

CGI ist bei mir auch nicht tot, sondern immer noch *das* Thema... Allerdings muß ich ja nicht auf WSGI deswegen verzichten und ich denke auch für neue User ist es besser, wenn sie direkt auf WSGI setzten... Ist ja auch mit einem CGIServer nicht viel anders als CGI, nur das einem die Welt (modPython, fastCGI ect.) offen steht...

Dein Beitrag hier, passt Optimal unter [wiki]Tipps und Tricks#Unicode[/wiki] :lol:

CMS in Python: http://www.pylucid.org
GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 1. Februar 2006, 22:35

jens hat geschrieben:Dein Beitrag hier, passt Optimal unter [wiki]Tipps und Tricks#Unicode[/wiki] :lol:
Hi Jens!

Dann würde ich aber ein wenig an der Beschreibung dieses Hauptpunktes drehen. ;-)

Tipps und Tricks - kurze Code Schnippsel

Das hat mich nicht wirklich angesprochen. Ich wollte ja eine Anleitung und kein Code-Schnippsel im Wiki unterbringen.

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

Mittwoch 1. Februar 2006, 23:09

Ich finde den Text auch gut. Textkodierung ist ja eine ziemlich verwirrende Angelegenheit, über die viele Leute früher oder später mal stolpern oder gar fallen. ;-)

Kleiner Verbesserungsvorschlag: Wenn man Zeichen ausserhalb der ASCII Kodierung ohne die "magische" Kommentarzeile in den Quelltext schreibt, dann gibt's eine Warnung und keinen Fehler.
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Donnerstag 2. Februar 2006, 04:43

gerold hat geschrieben:
jens hat geschrieben:Super Text!
Wäre eigentlich ideal für das Wiki... Aber du magst es nicht, was?
Hi Jens!

Danke. Aber du hast Recht -- Ich mag das Wiki immer weniger. Alleine, wenn ich mir den Verlauf (info) der Seite [wiki]Python im Web[/wiki]ansehe... Mit jeder neuen Version der Seite wurden immer mehr Infos unterschlagen und nur mehr für WSGI-Werbung benutzt.
Was ja auch so sein soll. WSGI ist nunmal ein PEP und soll verwendet werden.
Wenn ich die Infos der alten Seite http://www.pythonwiki.de/PythonWeb irgendwo unterbringen möchte, dann müsste ich alles komplett umschreiben. Ich lasse euch das Wiki als Spielwiese und hoffe nur, dass die Einträge des alten Wiki erhalten bleiben.
Wenn dir welche fehlen steck sie rüber, aber beide Wikis am Leben werden wir sicher nicht erhalten können. Wäre auch nicht Sinn der Sache.
CGI ist nicht tot und viele, die von PHP kommen, wünschen sich so etwas wie Servlets http://nick.gerf.org/pse/examples/tutorial.html oder Snakelets http://snakelets.sourceforge.net/manual/ypage.html.
Sollten sie aber nicht. CGI ist WSGI kompatibel und alles was das auch ist läuft über WSGI auf CGI. Unter anderem django und turbogears.
Aber davon steht nichts im Wiki und ich weiß nicht wo ich das dazuschreiben sollte.
Unter [wiki]Python im Web[/wiki]
PS: Wenn diese Anleitung nicht grob bemängelt wird, dann bitte ich dich, den reStructuredText zu nehmen und im Wiki an einem geeigneten Ort unter zu bringen. Ich kann ja nicht einfach in der Wiki-Hauptseite einen Eintrag für diese Anleitung machen. Also weiß ich auch in diesem Fall nicht wohin damit.
Werde ich tun.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Donnerstag 2. Februar 2006, 12:33

BlackJack hat geschrieben:Wenn man Zeichen ausserhalb der ASCII Kodierung ohne die "magische" Kommentarzeile in den Quelltext schreibt, dann gibt's eine Warnung und keinen Fehler.
Danke BlackJack!

Ich habe den Text geändert.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Freitag 3. Februar 2006, 11:56

Hi!

Jetzt konnte sich jeder mal die Anleitung durchlesen. Gibt es etwas was man ändern/korrigieren/umschreiben sollte (mit Begründung)? Ich bin für Vorschläge offen. Sie dürfen die Anleitung nur nicht komplizierter machen als sie bereits schon ist.

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Dienstag 23. Januar 2007, 22:36

Hi!

Ich habe mich ein bischen gespielt. Das Ergebnis ist ein kleines Python-Beispiel, in dem ich einen Unicode-String in eine Textdatei schreibe. Dabei wird dieser in das vom Betriebssystem bevorzugte Encoding umgewandelt. Danach öffne ich diese Textdatei wieder und lese sie aus. Dabei wird der ausgelesene Text automatisch wieder nach Unicode umgewandelt.

Seht selbst:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
Beispiel: Schreiben und Lesen von Textdateien.
          Von Unicode zu Textdateien im Standard-Encoding zu Unicode...
"""

import os
import codecs
import locale

FILENAME = "beispieltext.txt"


preferred_file_encoding = locale.getpreferredencoding()

unicode_text = \
u"""Ich bin ein Text mit Umlauten.
üäöß
ÖÄÜ"""

# In eine Textdatei schreiben. Dabei wird Unicode-Text 
# in das bevorzugte Encoding des Betriebssystems umgewandelt.
#
# Hierbei muss man berücksichtigen, dass ``codecs.open`` nicht wie
# bei ``open`` oder ``file`` üblich, automatisch die plattformtypischen
# Zeilenendzeichen einfügt. Auch dann nicht, wenn "w" statt "wb" als Modus
# angegeben wird. Man muss sich also selber darum kümmern.
f = codecs.open(FILENAME, "w", preferred_file_encoding)
unicode_lines = ["%s%s" % (line, os.linesep) for line in unicode_text.splitlines()]
f.writelines(unicode_lines)
f.close()

# Von einer Textdatei lesen und automatisch nach Unicode konvertieren.
# Dabei werden durch das "rU" die Zeilenendzeichen automatisch nach "\n" konvertiert.
f = codecs.open(FILENAME, "rU", preferred_file_encoding)
neuer_unicode_text = f.read()
f.close()

print "repr:", repr(neuer_unicode_text)
print "type:", type(neuer_unicode_text)
print
try:
    print neuer_unicode_text
except UnicodeEncodeError:
    print "konnte nicht direkt angezeigt werden"
Ich würde mir wünschen, dass in der nächsten Python-Version, die Funktion ``file`` einen ``encoding``-Parameter bekommen würde, so müsste man nicht mehr auf das Modul ``codecs`` ausweichen.

mfg
Gerold
:-)
Zuletzt geändert von gerold am Dienstag 23. Januar 2007, 23:47, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
sape
User
Beiträge: 1157
Registriert: Sonntag 3. September 2006, 12:52

Dienstag 23. Januar 2007, 23:37

Hi, Gerold. Von mir auch ein großes Danke schön!

Das hat mir damals sehr weitergeholfen, als ich Probleme mit dem Anzeige von umlauten hatte.

lg
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Mittwoch 24. Januar 2007, 00:31

Hi!

In dieser Version (ohne das ``codecs``-Modul) braucht man sich zwar nicht um die Zeilenendzeichen kümmern, dafür muss man bei großen Dateien aufpassen, dass man den Text nicht in einem Rutsch einliest und umwandelt. Das könnte vom Speicherverbrauch her ins Auge gehen.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
"""
Beispiel 2: Schreiben und Lesen von Textdateien.
            Von Unicode in eine Textdatei im bevorzugten Encoding des
            Betriebssystems und wieder zurück nach Unicode.
            
            In dieser Version braucht man sich zwar nicht um die Zeilenendzeichen
            kümmern, dafür muss man bei großen Dateien aufpassen, dass man den
            Text nicht in einem Rutsch einliest und umwandelt. Das könnte
            vom Speicherverbrauch her ins Auge gehen.
"""

import locale

FILENAME = "beispieltext.txt"


preferred_file_encoding = locale.getpreferredencoding()

unicode_text = \
u"""Ich bin ein Text mit Umlauten.
üäöß
ÖÄÜ"""

# In eine Textdatei schreiben. Dabei wird Unicode-Text
# in das bevorzugte Encoding des Betriebssystems umgewandelt.
f = file(FILENAME, "w")
f.write(unicode_text.encode(preferred_file_encoding))
f.close()

# Aus der Textdatei lesen und dabei nach Unicode umwandeln.
f = file(FILENAME, "rU")
neuer_unicode_text = f.read().decode(preferred_file_encoding)
f.close()

print "repr:", repr(neuer_unicode_text)
print "type:", type(neuer_unicode_text)
print
try:
    print neuer_unicode_text
except UnicodeEncodeError:
    print "konnte nicht direkt angezeigt werden"
lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Antworten