Text aus Datei einlesen:

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
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

Hallo miteinander. Ich habe eine kurze Frage:
ich möchte aus einer sehr langen Datei die Werte a - z auslesen:

ich bin eine Zahl
a b c x y z

wobei a - z Dezimalzahlen sind.
Daher dachte ich mir das ich in der Datei "ich bin eine Zahl" schnappe, was ein eindeutiger Hinweis ist und darauf irgendwie in die nächste Zeile springen sollte um die Werte auszulesen.
Folgender Ansatz funktioniert nicht, da ich keinen Zeilenumbruch hinbekomme, unten durch \n gekennzeichnet.
Kann jemand helfen?

Code: Alles auswählen

# Idee z.B. für den ersten Wert:
re_gk = re.compile("\s*ich\s*bin\s*eine\s*Zahl\s*\n\s*(?P<gk>[0-9]*\.?[0-9]+).*", re.I)

    res=re.match(re_gk, line)
    if res != None: 
        gk = float(res.group("gk"))   
               
print "GK: %s" % gk 
Danke für eure Hilfe
würmchen
User
Beiträge: 255
Registriert: Mittwoch 7. November 2007, 14:17

Ist es denn unter Windows oder Linux? Bei Windows sind es zwei Zeichen die einen Zeilenumbruch darstellen, vielleicht liegt es daran...
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

alles unter linux!
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Ich wuerde das ohne RegEx machen. Einfach mit einer for-Schleife ueber alle Zeilen wandern, schauen, ob die aktuelle Zeile "ich bin eine Zahl" ist, und dann die naechste Zeile lesen. Hat auch den Vorteil, dass du nicht die komplette Datei in den Speicher laden musst.

Ungetestet:

Code: Alles auswählen

f = open(...)
prevoious_line = ""

for line in f:
    if previous_line.strip() == "Ich bin eine Zahl":
        zahlen = line.split()
    previous_line = line
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Alternativlösung:

Code: Alles auswählen

from __future__ import with_statement
from itertools import dropwhile

def main():
    with open('test.txt') as lines:
        lines = dropwhile(lambda x: x != 'ich bin eine Zahl\n', lines)
        lines.next()    # Skip line with sentinel text.
        a, b, c, x, y, z = map(float, lines.next().split())
    print a, b, c, x, y, z
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

danke ersteinmal für die schnelle und kompetenten Antworten!
ich bin absoluter Anfänger, daher habe ich noch etwas Probleme und versuche irgendwie eine Lösung zu finden.

Code: Alles auswählen

    for line in inp:
        if line.strip() == "length of vectors":
            line = inp.next()
        print line
ich habe Häppchen aus euren Lösungen genommen und versuche es gerade so darzustellen das ich es auch verstehe.
Ich dachte das er mit obigem code die Zeile sucht, dann in die nächste Zeile springt und diese dann ausgibt. Statt dem Ausgeben würde ich dann mit RegEX die Zeile durchsuchen, aber das wäre dann nur die folge Aktion.
Aber wo ist hier gerade der Haken?
BlackJack

Gute Frage, wo ist er denn? Also ich meine was bekommst Du und wie unterscheidet sich das von Deiner Erwartung? Dir ist klar, dass Du im Moment alle Zeilen (ausser der mit dem Suchtext) ausgibst?
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

Ich habe gehofft das nur die auf Zeile, die auf "length of vectors" folgt ausgegeben wird.

-> pattern suchen -> Zeile: length of vectors
dann line = inp.next() # Springen in die folgende Zeile
in welcher meine gesuchten Zahlen sind: a b c x y z

Das ist mein Ziel ...
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

BlackJack hat geschrieben:Dir ist klar, dass Du im Moment alle Zeilen (ausser der mit dem Suchtext) ausgibst?
Ich kann mir vorstellen, dass du, baer, Zeile 4 nicht so einruecken willst wie sie dort eingerueckt ist.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

Das habe ich schon ausgetestet. Ich gebe einfach mal ein par mehr Zeilen an. Wenn ich das "print line" direkt zum Beginn einrücke gibt er mir alle Zeilen aus. Deswegen habe ich gehofft das er mit dem angeführten code nur die eine Zeile ausgibt, die auf "length of vectors folgt". *urghs*

Code: Alles auswählen

for line in inp.readlines():
    res=re.match(re_vol, line)
    if res != None: 
        vol = float(res.group("vol"))
    for line in inp:
        if line.strip() == "length of vectors":
            line = inp.next()
        print line
print "Volumen: %.2f \AA^3" % vol
Mad-Marty
User
Beiträge: 317
Registriert: Mittwoch 18. Januar 2006, 19:46

würmchen hat geschrieben:Ist es denn unter Windows oder Linux? Bei Windows sind es zwei Zeichen die einen Zeilenumbruch darstellen, vielleicht liegt es daran...
In beiden wird der newline mittels \n dargestellt aus python ...
BlackJack

@baer: *Was* hast Du denn mit der Einrückung ausprobiert? Das ist ja nun ein sehr übersichtliches Stück Quelltext, Du solltest mal Interpreter spielen, Dir eine kurze Textdatei ausdenken und das mal auf einem Blatt Papier durch spielen was Dein kurzer Quelltext da macht. Dann sollte eigentlich klar werden warum alle Zeilen bis auf die mit dem Suchtext ausgegeben werden.

Bei Deinem letzten Quelltext kann ich nur sagen: Nicht wild herum probieren ("programming by accident") sondern verstehen was Du da machst.

Dateien haben eine aktuelle Position bei der weitergelesen wird und bei jedem lesen einer Zeile wandert diese Position weiter. Wenn Du eine Datei einmal ausgelesen hast, ist diese Marke am Ende der Datei und man bekommt keine weiteren Zeilen mehr.

Die `readlines()`-Methode liesst alle Zeilen ein, dass heisst die innere ``for``-Schleife wird nicht ausgeführt, weil in `inp` einfach nichts mehr "drin" ist, die Datei ist ja schon komplett ausgelesen. Aber selbst wenn das funktionieren würde, würde diese Schleife für *jede* Zeile der Datei erneut ausgeführt, weil sie ja in der äusseren ``for``-Schleife steckt.

Hast Du das Tutorial aus der Dokumentation schon durchgearbeitet? Sind Dir so grundlegende Dinge wie ``for``-Schleifen wirklich klar?
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

Ich bin mir noch nicht sicher, aber ich glaube das ich halbwegs damit umgehen kann.
Ich habe nochmal den entscheidenden Teil isoliert

so sieht die Ausgabe der Datei aus, wobei es ein iteratives verfahren ist und ich nur den letzten hit benötige!

length of vectors
7.579211058 7.579211058 7.579211058 0.131939854 0.131939854 0.131939854

Dann das Skript

Code: Alles auswählen

#!/usr/bin/env python
import sys

try:
    inp = open("OUTCAR","r")
except:
    inp = None                
    print "Datei nicht vorhanden"
    sys.exit()

for line in inp.readlines():     
    previousline = ""              
    if previousline.strip() == "length of vectors": 
        inp.next()                   
        previousline = line 
print line
inp.close()
*grübel* was mache ich nur falsch ... *grübel*
baer
User
Beiträge: 11
Registriert: Dienstag 26. August 2008, 12:15

Da gibts noch viel zu lernen, aber ich habe es nun so gelöst:

Code: Alles auswählen

#!/usr/bin/env python
import sys

try:
    inp = open("OUTCAR","r")
except:
    inp = None
    print "Datei nicht vorhanden"
    sys.exit()

previousline = ""
for line in inp.readlines():
    line = line.strip()
    if  previousline == "length of vectors":
        actual_line = line
    previousline = line 
print actual_line
inp.close()
was auch zu funktionieren scheint! Danke auf jeden Fall schonmal für Eure Beiträge!
BlackJack

Das ``except`` ohne konkrete Ausnahme ist nicht schön. Damit wird bei *jeder* Ausnahme ausgegeben, dass die Datei nicht vorhanden sei, auch wenn das gar nicht stimmt. Zum Beispiel auch wenn das Programm an der Stelle mit CTRL-C abgebrochen wurde, kein Speicher mehr verfügbar ist, oder Du Dich in dem ``try``-Block irgendwo bei einem Namen vertippt hast und damit einen `NameError` oder einen `AttributeError` provozierst. Solche Fehler können dann sehr schwer zu finden sein weil wichtige Informationen einfach verschluckt bzw. durch eine irreführende Fehlermeldung ersetzt werden.

Den Aufruf von `readlines()` kannst Du Dir sparen und statt dessen einfach direkt über `inp` iterieren. Dann muss nicht die gesamte Datei auf einmal in den Speicher geladen werden.
Antworten