Textdateien zusammenfuehren

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
david
User
Beiträge: 30
Registriert: Montag 12. Januar 2004, 14:40

Hi!
Ich hab vor kurzem auch mit python angefangen und komme jetzt nicht mehr weiter.
Und zwar will ich aus einem Verzeichnis alle Textdateien einlesen und auswerten. In jeder Datei sind 303 Zeilen, davon sollen ersten 3 unberuecksichtigt bleiben. Die restlichen beinhalten 3 Werte wovon ich den ersten und den letzten benoetige. Die Werte sollen nun Zeilenweise aus allen Dateien nach einer bestimmten Formel zusammengefuegt werden und in eine Datei geschrieben werden.

Mein Problem besteht nun darin, dass ich es nicht hinbekomme, das ganze Zeilenweise zu erledigen, also alle Werte der 4 Zeile aus allen Dateien verrechnen, ausgeben und wieder von vorne anfangen, diesmal mit Zeile 5.

Ich suche keine komplette Loesung, sondern eher ein paar Anregungen zu verwendeten Modulen etc.

Vielen Dank!
Gruesse, David
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi david,

ich würde das über Iteratoren machen die über die Zeilen der Dateien iterieren.

Code: Alles auswählen

iter_f1 = iter(file("datei1.txt","r"))
iter_f2=iter(file("datei2.txt","r"))

for i in xrange(3): #die ersten drei Zeilen ueberspringen
    iter_f1.next()
    iter_f2.next()

for i in xrange(300):
    zeile_file1 = iter_f1.next()
    zeile_file2 = iter_f2.next()
    #mach was mit den Zeilen

Gruß

Dookie
david
User
Beiträge: 30
Registriert: Montag 12. Januar 2004, 14:40

Danke erstmal f*r Deine Antwort.

Da die Anzahl und auch der Name der Textdateien unterschieldich sein kann, kommt diese Methode leider nicht in Frage. Ich hatte eher an etwas mit dem Modul fileinput gedacht....

Gruesse, david
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi david,

du sagtest:
Mein Problem besteht nun darin, dass ich es nicht hinbekomme, das ganze Zeilenweise zu erledigen, also alle Werte der 4 Zeile aus allen Dateien verrechnen, ausgeben und wieder von vorne anfangen, diesmal mit Zeile 5.
Dazu habe ich mein kleines Beispiel gepostet.
Da die Anzahl und auch der Name der Textdateien unterschieldich sein kann, kommt diese Methode leider nicht in Frage. Ich hatte eher an etwas mit dem Modul fileinput gedacht....
Ja und macht doch nichts. Lies das Directory in eine Dateinamenliste ein, mach eine Liste mit Iteratoren die du mit Hilfe der Dateinamenliste erzeugst und für das Zusammenfügen kannst dann mein Beispiel ausbauen.

Code: Alles auswählen

import os
pfad = "daten"
filenames = os.listdir(pfad)
iter_list = []
for fname in filenames:
    iter_list.append(iter(file(fname,"r")))

for i in xrange(3): # die ersten drei Zeilen ueberspringen
    for iter_f in iter_list:
        iter_f.next()

for i in xrange(300):
    zeilex = []
    for iter_f in iter_list:
        zeilex.append(iter_f.next())
    #zeilex ist eine Liste der Zeilen 4+i der einzelnen Dateien
    print zeilex

Gruß

Dookie
david
User
Beiträge: 30
Registriert: Montag 12. Januar 2004, 14:40

Hi!
Danke für Diene Antwort!
Sorry, da war ich wohl etwas zu voreilig... :oops:

Ich werde mal in den nächsten Tagen versuchen Deine Tips umzusetzen. Wenn ich Hilfe benötige, weiß ich ja, wo ich sie finden kann.

Grüße, david
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi david,

fileinput ist nur für das sequenzielle Bearbeiten von Dateien gedacht, ums selber öffnen der Dateien wirst Du nicht rumkommen, und ist ja nicht so aufwändig. Stattt eine Liste mit den Iteratoren kannst Du auch ein Dictionary mitden Dateinamen als Keys verwenden, wenn Du die Dateienamen für die Zusammenführung der Daten brauchst. Oder halt vorher die Dateiliste sortieren.


Gruß

Dookie
david
User
Beiträge: 30
Registriert: Montag 12. Januar 2004, 14:40

So, hab nun noch ein wenig gebastelt. Bisher hab ich meine ursprüngliche fileinput - Version weiter verfolgt. Aber das ist mit zu chaotisch geworden.
Jetzt hab ich mir Deinen Vorschlag mal näher angeschaut. Kann es sein, dass iter erst ab python version 2.2 verfügbar ist? Ich verwende nämlich 2.1.3 und bekomme eine Fehlermeldung.
Ein update kommt nicht in Frage, da auf dem Zielcomputer später auch 2.1.3 verwendet wird. Und das zu ändern liegt nicht in meiner Macht...

Gibt es noch eine andere Möglichkeit?

Grüße, David
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

stimmt ich habe python 2.3. bei 2.1 musst Du wohl mit readline arbeiten

Code: Alles auswählen

import os
pfad = "daten"
filenames = os.listdir(pfad)
file_list = []
for fname in filenames:
    file_list.append(file(fname,"r"))

for i in xrange(3): # die ersten drei Zeilen ueberspringen
    for f in file_list:
        f.readline()

for i in xrange(300):
    zeilex = []
    for f in file_list:
        zeilex.append(f.readline())
    #zeilex ist eine Liste der Zeilen 4+i der einzelnen Dateien
    print zeilex

for f in file_list:
    f.close()
Gruß

Dookie
david
User
Beiträge: 30
Registriert: Montag 12. Januar 2004, 14:40

Eine Frage: Für was steht das "file" in der Zeile file_list.append(file(fname,"r")) ?
Ich nehme an, für das momentane file. Aber muss ich das nicht irgendwie zuweisen?

Sonst weiß python doch gar nicht, welches gemeint ist....


Fehlermeldung bei Ausführung des Skripts:

file_list.append(file(fname,"r"))
NameError: name 'file' is not defined


Grüße, David
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

uups, file ist bei Python 2.2 und 2.3 anstatt open, also ersetze das file(fname,"r") duch open(fname,"r").


Gruß

Dookie
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo!
Wenn das nicht übermäßig viele Dateien sind, würd' ich einen einfacheren Weg wählen. Erstmal alle Zeilen aller Dateien in Listen speichern, also für jede Datei eine Liste und dann die Listen elementweise (d.h. zeilenweise) mittels z.B. zip() zusammenführen.

Code: Alles auswählen

import os

pfad = "c:\\tmp"
filenames = os.listdir(pfad)

listeVonListen = []
for fname in filenames:
    listeVonListen.append(open(pfad+"\\"+fname,"r").readlines()[3:])

znr = 1
for zeilen in zip(*listeVonListen):
    print znr,zeilen   # Ausgabe der Zeilen (als Liste) aller Dateien der soundsovielten Zeile
    znr += 1
Jan
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Dookie hat geschrieben:stimmt ich habe python 2.3. bei 2.1 musst Du wohl mit readline arbeiten
Davor gabs aber auch schon xreadlines. opened_file.xreadlines() gibt auch einen Iterator über die Zeilen zurück...
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Hi Milan,

aber xreadlines ist kein richtiger iterator, das funktioniert nur mit for ansonst muss man es in eine Liste umwandeln und schon ist der Vorteil von Iteratoren weg.

Code: Alles auswählen

xro = xreadlines(open("test.txt","r"))
zeile = xro.next() # geht nicht!!!
auch pop() kennt xreadlines nicht


Gruß

Dookie
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Tut mir leid Dookie, das ist doch ein Iterator :wink: Ich hab in eine Datei test.txt "Ich\bin\nhier\n" geschrieben. Das ist das Ergebniss, getestet unter Python 2.2.1 bzw. 2.1:

Code: Alles auswählen

>>> f=open('test.txt','r')
>>> s=f.xreadlines()
>>> s.next()
'ich\n'
>>> s.next()
'bin\n'
>>> s.next()
'hier\n'
>>> s.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
StopIteration
Aber ne andere Sache: was leistet pop? Wenn ich mir unter 2.3 einen Iterator bastle, kennt der das auch nicht:

Code: Alles auswählen

>>> def it():
	yield 1
	yield 2
>>> s=it()
>>> s.pop()
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in -toplevel-
    s.pop()
AttributeError: 'generator' object has no attribute 'pop'
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

mit 2.2 gehts, mit 2.1 nicht

Code: Alles auswählen

fritz@seneca:~$ python2.1
Python 2.1.3+ (#1, Jul  5 2003, 00:42:30)
[GCC 3.3.1 20030626 (Debian prerelease)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> f = open("test.txt","r")
>>> s=f.xreadlines()
>>> s.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
AttributeError: 'xreadlines' object has no attribute 'next'
>>>

Gruß

Dookie
david
User
Beiträge: 30
Registriert: Montag 12. Januar 2004, 14:40

So, ich hab jetzt das Skript in der ersten Rohversion fertiggestellt. Es gibt noch an allen möglichen Stellen was zu verbessern und zu verkürzen, aber trotzdem will ich es mal hier reinstellen.
Ich hab jetzt nämlich doch nicht den Ansatz von Dookie genommen, sondern meine erste Idee, nämlich das ganze über das Modul fileinput zu machen, weiterverfolgt. Aber seht selbst...

Code: Alles auswählen

#!/usr/bin/env python

import os,fileinput,string,sys,math


pfad=os.listdir(os.curdir)
print pfad


zout=4
def read_line(zin):
    zout=zin
    l_1=[]
    l_2=[]
    for line in fileinput.input(pfad):


        dateiname=fileinput.filename()
        dateizeile=fileinput.filelineno()

        if dateiname == 'zusammenzieh.py':
            pass
        elif dateiname == 'ausgabe.txt':
            pass
        else:
            if dateizeile<zin:
                pass
            else:

                data=string.split(line)
                a=string.atof(data[0])                   #wandelt string in float und schreibt in liste
                b=string.atof(data[2])

                l_1.append(a)
                l_2.append(b)


                fileinput.nextfile()

    if 0 in l_2:
        sigma=0
        x=0

    else:
        sigma=1/(math.sqrt(1/(l_2[0]**2)+1/(l_2[1]**2)+1/(l_2[2]**2)+1/(l_2[3]**2)+1/(l_2[4]**2)))
        sum_sigma_square=1/( 1/(l_2[0]**2) + 1/(l_2[1]**2) + 1/(l_2[2]**2) + 1/(l_2[3]**2) + 1/(l_2[4]**2) )
        sum_x_sigma_square=l_1[0]/(l_2[0]**2) + l_1[1]/(l_2[1]**2) + l_1[2]/(l_2[2]**2) + l_1[3]/(l_2[3]**2)\
        + l_1[4]/(l_2[4]**2)
        x=sum_x_sigma_square * sum_sigma_square

    text=str(x) + '\t' + str(sigma)+'\n'      #+'\n': fügt dem string einen zeilevorschub hinzu

    output=open('ausgabe.txt','a')      #a-> neue daten werden immer hinten an geschrieben
    output.write(text)
    output.close()

    return zout


while zout < 304:
    read_line(zout)
    zout=zout+1


raw_input('Press Enter to terminate')


Nochmal herzlichen Dank an alle!

Grüße, david
Antworten