Seite 1 von 2

Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 12:22
von api
Hallo zusammen,

ich möchte einfach eine Datei einlesen und am Bildschirm ausgeben.

Inhalt der Datei (infile):
*************
Österreich
*************

Das Programm hierzu:

Code: Alles auswählen

#! /opt/python3.1/bin/python3
# -*- coding: iso-8859-15 -*-

##################################################################################################
import os
import sys
import codecs
import locale

infile = /tmp/umlaut.txt"

FileEncoding = locale.getpreferredencoding()
print ("Locale: %s" % FileEncoding)

IN_File = codecs.open(infile, 'r', FileEncoding).readlines()

print (IN_File)
Wenn in der Datei keine Umlaute vorkommen, funktioniert es auch...

Habt ihr einen Vorschlag?

CU,
Api

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 12:34
von deets
Wie waers denn mit dem encoding des Files, statt einem preferred encodings deines Systems? Und bevor du fragst: nein, das kann Python nicht selbst bestimmen, man muss generell (es gibt wenige Ausnahmen wie XML) immer wissen, in welchem Encoding ein File gespeichert wurde.

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 12:44
von api
Was meinst du denn genau mit einem "encoding" der Datei?

Dieses funktioniert leider nicht... Kannst du mir sagen, wie das sein muss?

Code: Alles auswählen

#! /opt/python3.1/bin/python3
# -*- coding: iso-8859-15 -*-

##################################################################################################
import os
import sys
import codecs
import locale

infile = /tmp/umlaut.txt"

FileEncoding = locale.getpreferredencoding()
print ("Locale: %s" % FileEncoding)

IN_File = open(infile, 'r').readlines()
IN_File = IN_File.encode('iso-8859-15')

print (IN_File)


Traceback (most recent call last):
File "umlaut", line 18, in <module>
IN_File = IN_File.encode('iso-8859-15')
AttributeError: 'list' object has no attribute 'encode'

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 12:51
von deets
Du hast doch in deinem originalen Code eine Variable "FileEncoding". Und die musst du auf das encoding des files setzen.

Dein zweites Snippet ist voelliger Quatsch, weil du da eine Datei einliest als Liste von Zeilen, und die dann dekodieren willst, als ob's ein String waere. Das geht natuerlich nicht.

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 13:04
von api
Wie finde ich denn heraus, welches Encoding mein File hat?

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 13:10
von deets
*seufz*

Das habe ich doch schon im ersten Post geschrieben - das weiss niemand, ausser dir. Bzw. demjenigen, der die Datei geschrieben hat. Man kann ein bisschen raten, aber eine Garantie gibt es nicht. Darum solltest du das schon selbst wissen.

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 13:36
von api
Nun ja, ich weiss nu nicht so recht, was ich da machen soll... :-((

Ich befinde mich hier unter UNIX, habe die Datei selbst verfasst und dann abgespeichert.

Unter Coding verstehe ich eigentlich, dass ich diese Datei wohl als ""iso-8859-1" oder halt ""iso-8859-15" angelegt habe. Oder ist das schon falsch?

Aber ein
FileEncoding = "iso-8859-1"
funktioniert eben auch nicht - wahrscheinlich, weil etwas grundsätzliches falsch ist!?

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 13:47
von JonasR
Unter linux kannst du

Code: Alles auswählen

file DATEINAME
eingeben und schon hast du das encoding.
Funktioniert zumindest bei mit mit vi erstellten Datein ;)

Code: Alles auswählen

xxx:~# file test.txt
test.txt: ISO-8859 text

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 13:55
von deets
@api

Ob iso-8859-1 richtig oder falsch ist musst du schon selbst wissen. Wenn es denn alle Umlaute & Sonderzeichen abbilden kann, die dich interessieren, dann reicht es schon.

Und leider ist deine Fehlerbeschreibung von 'es geht nicht' aeusserst duerftig. Mit einem byte-encoding wie latin1 (anderer Name fuer iso-8859-1) bist du an sich naemlich in einer Situation, so ziemlich *alles* einlesen zu koenne. Kommt Gruetze bei rum, aber keine Exception zB.

Insofern: was genau machst du, und was schlaegt fehl?

Edit: hier mal ein kleiner test, der das veranschaulicht, das latin1 immer geht:

Code: Alles auswählen

l = []

for i in xrange(256):
    l.append(chr(i))

s = "".join(l)

u = s.decode("latin1") # geht immer
print u.encode("utf-8") # mein terminal hat utf-8
u = s.decode("utf-8") # geht nicht

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 14:10
von api
@deets

Mein Programm sieht zur Zeit so aus:

Code: Alles auswählen

#! /opt/python3.1/bin/python3
# -*- coding: ascii -*-

##################################################################################################
import os
import sys
import codecs
import locale

infile = "/tmp/umlaut.txt"

FileEncoding = "latin1"

IN_File = codecs.open(infile, 'r', FileEncoding).readlines()

print (IN_File)
Und die Fehlermeldung lautet:
File "umlaut", line 20, in <module>
print (IN_File)
UnicodeEncodeError: 'ascii' codec can't encode character '\xd6' in position 21: ordinal not in range(128)

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 14:12
von api
@JonasR

Ich befinde mich leider zur Zeit nicht unter Linux - sondern unter UNIX. Somit ergibt die Anweisung
file umlaut.txt
umlaut.txt: data

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 14:22
von api
@deets

Noch mal als Hinweis am Rande. Ich benutze Python 3.1 ! (siehe 1. Zeile)

Unter Python 2.4.6 habe ich dieses Problem nicht... Da funktioniert das.

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 14:53
von deets
Siehste, und schon wird es klarer, wenn du genug Infos gibst: dein Problem ist mitnichten das *einlesen* der Datei, sondern die Ausgabe ihres Inhaltes. Und so, wie ich das in meinem Snippet gemacht habe, musst du das auch machen - naemlich den unicode-string von Python vor der Ausgabe zu einem byte-string in einem encoding wandeln, das dein Terminal versteht. Welches das ist, kannst auch wieder nur du wissen, meines ist wie gesagt utf-8.

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 15:06
von api
@deets

Ja - super! Jetzts läufts auch wie gewünscht...

Code: Alles auswählen

#! /opt/python3.1/bin/python3
# -*- coding: ascii -*-

##################################################################################################
### -*- coding: iso-8859-15 -*-
##################################################################################################
import os
import sys
import codecs
import locale

infile = "/tmp/umlaut.txt"

FileEncoding = "ISO-8859-15"

IN_File = codecs.open(infile, 'r', FileEncoding).readlines()

for line in IN_File:
  print (line.encode(FileEncoding))
So werden genau die Zeilen dargestellt, die auch in der Datei stehen.

Du hast mir wirklich weitergeholfen. Danke dir :D

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 15:34
von CM
api hat geschrieben:Ich befinde mich leider zur Zeit nicht unter Linux - sondern unter UNIX. Somit ergibt die Anweisung
file umlaut.txt
umlaut.txt: data
$man file hat geschrieben:Any file that cannot be identified as having been written in any of the character sets listed above is simply said to be ‘data’.
Alles klar? Das hat was mit 'file' und Deiner Datei, aber nicht mit Deinem OS flavour zu tun.

Im Übrigen ist ein Konstrukt wie

Code: Alles auswählen

infile = open(...).readlines()
for line in infile: pass
infile.close()
# anstelle von
infile = open(...)
for line in infile: pass
infile.close()
# oder
with open(...) as infile:
    for line in infile: pass
sehr unschön (Speicherverbrauch, Speed, Redundanz).

HTH
Christian

PS Mal abgesehen davon, daß Listen keine close()-Methode haben :oops: ('infile' wäre im ersten Teil eine Liste, kein Fileobjekt, wie Du vielleicht vermutet hast, api.)

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 16:03
von api
@CM

Danke für den Hinweis. Habe das Script dann mal so angepasst:

Code: Alles auswählen

#! /opt/python3.1/bin/python3
# -*- coding: ascii -*-

##################################################################################################
### -*- coding: iso-8859-15 -*-
##################################################################################################
import os
import sys
import codecs
import locale

infile = "/tmp/umlaut.txt"

FileEncoding = "ISO-8859-15"

with codecs.open(infile, 'r', FileEncoding) as f:
  for line in f:
    print (line.encode(FileEncoding))
Muss ich denn jetzt bei diesem Kontrukt am Ende noch ein

Code: Alles auswählen

f.close()
einsetzen oder nicht?

Und dann noch zu deinem Statement...
Alles klar? Das hat was mit 'file' und Deiner Datei, aber nicht mit Deinem OS flavour zu tun.
Was meinst du damit? Ich habe schließlich eine ganz normale Datei (mit vi erzeugt).

CU,
Api

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 16:14
von CM
api hat geschrieben:Muss ich denn jetzt bei diesem Kontrukt am Ende noch ein

Code: Alles auswählen

f.close()
einsetzen oder nicht?
Nein, with kümmert sich drum.
api hat geschrieben:Was meinst du damit? Ich habe schließlich eine ganz normale Datei (mit vi erzeugt).
Das kann schon sein. Aber aus irgendeinem Grund erkennt file nicht mehr als 'data'. Das kann an vielen Dingen liegen, aber nicht daran, daß Du ein bestimmtes Unix-flavour nutzt. Vielleicht ist magic (worauf file zurückfällt) bei dem System irgendwie nicht so umfangreich?

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 16:23
von api
@CM

Also, wenn ich mit vi eine Datei erfasse (test.txt), mit folgendem Inhalt:
test:
Dann der test mit "file"
file test.txt
test.txt: ascii text
Wenn die Datei Umlaute enthält:
test:Ö
Dann der test mit "file"
file test.txt
test.txt: data
Das müsste doch bedeuten, dass das OS das nicht lesen kann, oder?

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 17:26
von BlackJack
@api: Wie ja schon von deets geschrieben wurde, kann man die Kodierung einer Textdatei nicht automatisch ermitteln, sondern höchstens raten. Wenn nur Werte im (druckbaren) ASCII-Bereich vorkommen, vermutet ``file``, dass es sich wohl um ASCII handelt. Bei ``test:Ö`` ist (fast) unabhängig von der verwendeten Kodierung klar, dass es nicht ASCII ist. Also sagt Dein ``file`` es sind allgemein Daten. Das ist der Fallback, der nie falsch ist. Denn ganz allgemein enthält eine Datei immer Daten.

Re: Einfache Datei mit Umlauten einlesen

Verfasst: Freitag 8. Juli 2011, 21:35
von CM
Nee, file sollte das Beispiel eindeutig als ein Unicode-flavour erkennen - auch wenn das encoding nicht im vimrc gesetzt ist. Der Algorithmus von file sieht vor systematisch durchzuraten und erst wenn gar nichts Näherliegendes erkannt wird, greift file auf 'data' zurück. Aber, api, ich würd' mich mal davon frei machen den Fehler beim OS zu suchen. Allenfalls, wenn Du an einer wirklich alten Maschine sitzt, könnte die mangelnde Wartbarkeit dazu führen, daß Deine 'file'-Version schlechter rät. Aber 'data'? - Das kommt mir immer noch komisch vor. (Auf VAX/VMS habe ich unabsichtlich immer wieder mal Zeichen erzeugt, die zum Teil gar nicht dargestellt wurden. Da war Debugging ein besonderer Spaß ;-) . Selbst da war das OS "unschuldig".)