Seite 1 von 1

Textdateien zusammenfuehren

Verfasst: Montag 12. Januar 2004, 14:50
von david
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

Verfasst: Montag 12. Januar 2004, 15:44
von Dookie
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

Verfasst: Montag 12. Januar 2004, 15:58
von david
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

Verfasst: Montag 12. Januar 2004, 16:32
von Dookie
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

Verfasst: Dienstag 13. Januar 2004, 16:30
von david
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

Verfasst: Dienstag 13. Januar 2004, 18:54
von Dookie
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

Verfasst: Dienstag 13. Januar 2004, 20:30
von david
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

Verfasst: Dienstag 13. Januar 2004, 20:50
von Dookie
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

Verfasst: Dienstag 13. Januar 2004, 21:12
von david
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

Verfasst: Dienstag 13. Januar 2004, 21:25
von Dookie
uups, file ist bei Python 2.2 und 2.3 anstatt open, also ersetze das file(fname,"r") duch open(fname,"r").


Gruß

Dookie

Verfasst: Dienstag 13. Januar 2004, 21:37
von Voges
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

Verfasst: Mittwoch 14. Januar 2004, 08:24
von Milan
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...

Verfasst: Mittwoch 14. Januar 2004, 16:16
von Dookie
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

Verfasst: Mittwoch 14. Januar 2004, 16:38
von Milan
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'

Verfasst: Mittwoch 14. Januar 2004, 19:40
von Dookie
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

Verfasst: Freitag 16. Januar 2004, 20:32
von david
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