Seite 1 von 1

4 Zeilen einer Datei in ein array/dictionary einlese

Verfasst: Sonntag 29. März 2009, 13:05
von egerlach
[edit: selbst geloest, siehe unten]
Hallo,
habe hier Dateien der Art:

Hans
Müller
Musterstr. 5
77777 Musterstadt
01.01.2000

Diese sollen in ein Dictionary eingegelesen werden, auf das ich dann so zugreifen will:
person[vorname]
person[nachname]
person[strasse]
....

Das ganze als Funktion, die mir "person" als Variable zurückgibt:
def leseDatei

Ich finde die Syntax zum definieren und einlesen der Felder nicht. Öffnen und ausgeben kann ich die Datei:

Code: Alles auswählen

outfile="/home/test/export.txt"
file=open(outfile)
data=file.read()
lines=data.splitlines()
print lines[0]
print lines[1]
print lines[2]
print lines[3]
Nur eben nicht tupel mit Namen zuordnen.
Gruss
Eckard

edit: jetzt habe ich fast ne Stunde gesucht und eine Minute nach dem Posting hier finde ich es selbst:

Code: Alles auswählen

person = {}
person['nachname'] = lines[0]
person['vorname'] = lines[1]
print person['nachname']
....

Verfasst: Sonntag 29. März 2009, 13:13
von Nocta
Man sollte ``file`` nicht als Variable verwenden, weil es ein Schlüsselwort ist.

Code: Alles auswählen

lines = [i for i in f.readlines()]
person = {'vorname':lines[0], 'nachname':lines[1], ...}
So würde ich das machen.

person ist dann vom Typ ``dict``, ein Dictionary.

Verfasst: Sonntag 29. März 2009, 13:33
von egerlach
[quote="Nocta"]

Code: Alles auswählen

lines = [i for i in f.readlines()]
person = {'vorname':lines[0], 'nachname':lines[1], ...}
Danke! Bei Deiner Lösung allerdings immer noch ein "return" am Ende von jeder Zeile dran - so wie es in der Urspungsdatei auch ist. Wie bekomme ich das return elegant weg? - Mit splitlines ist KEIN return am ende.

Verfasst: Sonntag 29. März 2009, 13:35
von cofi
Nocta hat geschrieben:

Code: Alles auswählen

lines = [i for i in f.readlines()]
Das ist ja mal ein interessantes Stück *hust*

Der Ansatz hat einen Nachteil: Du liest die ganze Datei in den Speicher. Hast du
bei dem Dateiformat irgendwelche Trenner? Sind das immer 5 Zeilen pro Eintrag?

Wenns immer 5 sind und es keine Trenner gibt:

Code: Alles auswählen

def read_person(fobject):
    person = {}
    person["vorname"] = fobject.readline().strip()
    person["nachname"] = fobject.readline().strip()
    person["strasse"] = fobject.readline().strip()
    ...
    return person

Verfasst: Sonntag 29. März 2009, 13:46
von Nocta
cofi hat geschrieben:
Nocta hat geschrieben:

Code: Alles auswählen

lines = [i for i in f.readlines()]
Das ist ja mal ein interessantes Stück *hust*

Der Ansatz hat einen Nachteil: Du liest die ganze Datei in den Speicher
*Auf den Rücken klopf* was ist denn daran so interessant? Würde mir mehr helfen, wenn du deine Kritik äußern würdest :)

Ich dachte die Datei hat nur diese 5 Zeilen, dann macht's ja nichts, wenn man alles auf einmal einliesst :)
Bei Deiner Lösung allerdings immer noch ein "return" am Ende von jeder Zeile dran
Wenn du damit das \n meinst:
lines[x][0:-1]
Edit: bzw. das von Cofi benutzte .strip()

Verfasst: Sonntag 29. März 2009, 13:53
von egerlach
Also die Lösung von cofi , die mit fobject.readline().strip() passt einwandfrei.
Zu Info: die Dateien, die ich immer wieder öffne haben ein paar dutzend bis hin zu ein paar hundert Zeilen, jede Zeile ein bißchen lesebarer Text. Es macht nichts, wenn die Dateien komplett eingelesen werden, es wird immer nur eine Datei eingelesen und dann passiert länger nichts. Es werden KEINE hundert oder tausende Dateien hintereinander gelesen.

Verfasst: Sonntag 29. März 2009, 13:58
von BlackJack
@Nocta: `file.readlines()` liest alle Zeilen ein und liefert eine Liste damit zurück. Und Du kopierst die dann mit einer "list comprehension" noch einmal in eine neue Liste, was irgendwie etwas sinnlos ist.

Und noch ein Vorschlag:

Code: Alles auswählen

def read_person(in_file):
    keys = ['vorname', 'nachname', 'strasse', 'ort', 'datum']
    return dict(zip(keys, (line.strip() for line in in_file)))

Verfasst: Sonntag 29. März 2009, 13:58
von cofi
Nocta hat geschrieben:*Auf den Rücken klopf* was ist denn daran so interessant? Würde mir mehr helfen, wenn du deine Kritik äußern würdest :)
Du machst nichts anderes als das, was .readlines() schon macht ;)
Nocta hat geschrieben:Ich dachte die Datei hat nur diese 5 Zeilen, dann macht's ja
nichts, wenn man alles auf einmal einliesst :)
Gut, dann hätte ich das missverstanden. Der Vorteil meines Ansatzes ist
allerdings, dass er mit beidem klarkommt ;)
Nocta hat geschrieben:Wenn du damit das \n meinst: lines[x][0:-1]
Es gibt `.strip()' bzw `.rstrip()'

Verfasst: Sonntag 29. März 2009, 14:28
von Nocta
Hm, okay, ich dachte gerade irgendwie, dass readlines() nur jeweils die nächste Zeile lesen würde.
Das ist aber readline ohne s :) Aber das wäre dann natürlich auch sinnlos, wozu readline() aufrufen, wenn man das selbe auch mit readlines() schafft?
Im Prinzip sollte das dann so in der Richtung wie BlackJack's Vorschlag sein, nur dass sich das ganze nicht automatisch per zip() zusammengefügt hat :p

Schön dass man hier auch als nicht-Thread-Eröffner immer was lernt bzw seine dummen Gedanken ausgetrieben kriegt :D

Verfasst: Sonntag 29. März 2009, 19:20
von str1442
@Nocta:

Du meinst file ist ein bereits existierender Name, der sich von eigenen Namen / Variablen nicht unterscheidet. Ein Schlüsselwort ist alles, was hier grün dargestellt wird - for, try, except usw.

Ein file object ist ein iterable und nebenbei auch sein eigener Iterator, deswegen kannst du auch du readlines im Grunde so nachbauen:

Code: Alles auswählen

[line for line in file_obj]
Deine Version davon mit readlines macht das im Grund dann zweimal hintereinander.
Aber das wäre dann natürlich auch sinnlos, wozu readline() aufrufen, wenn man das selbe auch mit readlines() schafft?
readlines() liest die gesamte Datei komplett in den Speicher. Sofern du sie aber immer nur nach und nach brauchst, ist das ineffizient. Stattdessen könntest du entweder einfach nur das Datei Objekt nehmen, eben readline (oder next, da es ja sein eigener Iterator ist) benutzen, oder auch eine Generator Expression ala "(line for line in file_obj)" (was zwar auch nicht sinnvoller wäre, als file_obj direkt zu nehmen, aber immerhin nicht schlechter ist).

Und i sollte man nur für Zahlen als Variable benutzen, die als Zähler dienen, nicht einfach für beliebige Objekte.