4 Zeilen einer Datei in ein array/dictionary einlese

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.
Antworten
egerlach
User
Beiträge: 43
Registriert: Samstag 14. März 2009, 21:32

[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']
....
Zuletzt geändert von egerlach am Sonntag 29. März 2009, 13:17, insgesamt 2-mal geändert.
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

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.
egerlach
User
Beiträge: 43
Registriert: Samstag 14. März 2009, 21:32

[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.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

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
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

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()
Zuletzt geändert von Nocta am Sonntag 29. März 2009, 13:56, insgesamt 1-mal geändert.
egerlach
User
Beiträge: 43
Registriert: Samstag 14. März 2009, 21:32

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.
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)))
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

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()'
Nocta
User
Beiträge: 290
Registriert: Freitag 22. Juni 2007, 14:13

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
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@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.
Antworten