Seite 1 von 1

Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Donnerstag 15. Juli 2010, 23:23
von ratna_fong
Hallo zusammen, :D

erlaubt mir bitte zum Punkt zu kommen:

datei001.txt :
zeile 1
zeile 2
zeile 3


datei002.txt:
zeile 4
zeile 5
zeile 6


datei003.txt:
zeile 7
zeile 8
zeile 9


Ich habe folgenden Code:

Code: Alles auswählen

import sys

final = open("ergebnis.txt", "wb")

for i in range(1,4) :
    temp = open("hrl00" + str(i) + ".txt", "r")
    for line in temp:
        final.write(line)
    temp.close()
final.close()

Code funktioniert, d.h. Ergebnis sieht wie erwünscht aus. Code zwar eventuell nicht so elegant, aber mir macht das nichts.

ergebnis.txt:

zeile 1
zeile 2
zeile 3
zeile 4
zeile 5
zeile 6
zeile 7
zeile 8
zeile 9


Nun, ich möchte etwas komplizierter machen. Wenn der Inhalt der Dateien sagen wir mal so aussieht:

datei001.txt:
Überschrift
Zeile 1
Zeile 2

datei002.txt:
Überschrift
Zeile 3
Zeile 4

datei003.txt:
Überschrift
Zeile 5
Zeile 6

Am Ende soll also so rauskommen:

Ergebnis.txt:

Überschrift
Zeile 1
Zeile 2
Zeile 3
Zeile 4
Zeile 5
Zeile 6

Bis auf die Erste soll also aus jeder Datei jeweils ab der 2. Zeile in ergebnis.txt geschrieben werden.
Habt Ihr vielleicht mal eine Idee? Ich danke Euch für Eure Hilfe.

Viele Grüße,

Eure Ratna :oops:

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Donnerstag 15. Juli 2010, 23:53
von EyDu
Du möchtest enumerate oder itertools.islice verwenden.

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 01:05
von ratna_fong
vielen Dank für den Tipp, hab ich direkt probiert. :D Erstmal ganz einfach, allerdings schon direkt mit Fehlern behaftet :(

Code: Alles auswählen

import itertools

final = open("datei.txt", "r")
endfinal = itertools.islice(final, 1, None)
print endfinal
final.close()
Ich hab also versucht, die 1. Zeile auszulassen und den Rest zu printen.
vielleicht liegts an final als Parameter in der Methode? final ist doch iterierbar, müsste doch eigentlich klappen.
Mhhh..

Danke für die Hilfe.

Eure Ratna :oops:

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 02:32
von pillmuncher
ratna_fong hat geschrieben:Code funktioniert, d.h. Ergebnis sieht wie erwünscht aus. Code zwar eventuell nicht so elegant, aber mir macht das nichts.
Mir schon. Und dir auch, selbst, wenn du es jetzt noch nicht glaubst. Es ist aber nichtmal eine Frage der Eleganz, sondern eine bzgl. der Fehleranfälligkeit. Wenn du with ...: verwendest, ist garantiert, dass die Datei wieder geschlossen wird. So wie du das machst, bleibt die Datei geöffnet, wenn zwischen file = open() und file.close() eine Exception fliegt, denn dann wird letzteres nicht ausgeführt.

Und Strings mit + zusammenzubasteln, ist meistens auch nicht klug.

Versuch lieber das hier:

Code: Alles auswählen

with open("ergebnis.txt", "wb") as out_file:
    for num in xrange(1,4):
        with open("hrl00%d.txt" % num, "r") as in_file:
            # <-- hier die erste Zeile aus dem gerade geöffneten in_file lesen
            # <-- hier die gelesene Zeile des ersten in_files in das out_file schreiben
            out_file.writelines(in_file)
Dann willst du natürlich das hier lesen.

Oder du machst es wie EyDu beschrieben hat, das geht genauso. Du schreibst zwar was von "mit Fehlern behaftet", aber bei mir funktioniert dein Code fehlerfrei. Was du als Fehler bezeichnest, ist vermutlich eine Ausgabe der Art <itertools.islice object at 0x00D4AF90>. Das ist vielleicht nicht das, was du erwartest, aber es ist das, was du programmiert hast. Versuch mal:

Code: Alles auswählen

print ''.join(endfinal)

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 12:53
von ratna_fong
vielen Dank pillmuncher und Anderen,

richtig, "mit Fehlern behaftet" war falsch ausgedrückt, eine unerwartete Ausgabe wäre schon eher gewesen.
Ich habe den Vorschlagcode noch drangehangen und es hat einwandfrei funktioniert. Also:

Code: Alles auswählen

print ''.join(endfinal)
Ich frage mich noch warum mein simpler Code eigentlich nicht das ausgibt, was ich wollte. Ich habe ein bisschen gegoogelt und in die Dokumentation reingeschaut. Es steht, dass die Methode itertools.islice "Make an iterator that returns selected elements from the iterable", also, sie spuckt bestimmte Elemente eines Interators. Meine datei.txt sieht doch so aus:

Überschrift
Zeile 1
Zeile 2

Und open spuckt doch ein Fileobjekt aus, einen Iterator zeilenweise. Habt Ihr vielleicht einen Denkfehler hierbei entdeckt? Wäre mir echt dankbar.

Code: Alles auswählen

import itertools

final = open("datei.txt", "r")
endfinal = itertools.islice(final, 1, None)
print endfinal
final.close()
 
Schöne Grüße,

Eure Ratna

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 13:08
von Hyperion
Du willst doch mehrere Dateien joinen.

Also musst Du das ganze schon mal in eine Funktion packen, die Du für mehrere Dateien nutzen kannst. Die Funktion braucht also den Dateinamen und eine Info, ob es sich um die erste Datei handelt, bei der ja die Überschrift mitgenommen werden soll.
Diese Info kann man letztlich als Startparameter der islice()-Funktion ansehen, also einfach ein Integer.

Bei der ersten Datei übergibst Du also eine 0, danach jeweils eine 1.

Code: Alles auswählen

def append_data(filename, startline):
    with open(filename, "r") as infile:
        return "\n".join(islice(infile, startline, None))
Nun musst Du nur noch eine Dateiliste erstellen und dazu den Startwert speichern. (Man könnte es mit Tupeln oder einem Dictionary lösen) Dann kannst Du die Rückgabewerte entsprechend joinen und am Schluss in eine Datei schreiben :-)

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 13:31
von BlackJack
@Hyperion: Die Funktion ist unschön. Der Name scheint nicht zu passen, ausserdem sehe ich den Sinn von dem `join()` nicht. Zumal das Zeilenende da zuviel ist, denn die eingelesenen Zeilen haben das Zeichen ja selbst noch.

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 14:32
von Hyperion
BlackJack hat geschrieben:@Hyperion: Die Funktion ist unschön. Der Name scheint nicht zu passen,
Stimmt! Als ich anfing hatte ich eine etwas andere Idee.
ausserdem sehe ich den Sinn von dem `join()` nicht. Zumal das Zeilenende da zuviel ist, denn die eingelesenen Zeilen haben das Zeichen ja selbst noch.
Ich dachte, dass man am Schluss alles als String zusammen setzen möchte. Aber ok man kann natürlich auch den Iterator zurückgeben und das ganze dann in der main() zusammensetzen. Ja, an die Zeilenendzeichen habe ich irgendwie nicht gedacht.

Aber hey, heute ist Freitag und im Büro hier gefühlte 35° ;-)

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 16:03
von BlackJack
@Hyperion: Man kann es auch überhaupt nicht zusammensetzen, es soll ja wieder in eine Datei geschrieben werden und Dateiobjekte haben was symmetrisches zu `readlines()`. ;-)

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 17:33
von Hyperion
BlackJack hat geschrieben:@Hyperion: Man kann es auch überhaupt nicht zusammensetzen, es soll ja wieder in eine Datei geschrieben werden und Dateiobjekte haben was symmetrisches zu `readlines()`. ;-)
Hyperion hat geschrieben: Aber hey, heute ist Freitag und im Büro hier gefühlte 35° ;-)
:mrgreen:

Stimmt. So wollte er es haben :-)

Re: Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

Verfasst: Freitag 16. Juli 2010, 19:48
von pillmuncher
ratna_fong hat geschrieben:Ich habe ein bisschen gegoogelt und in die Dokumentation reingeschaut. Es steht, dass die Methode itertools.islice "Make an iterator that returns selected elements from the iterable", also, sie spuckt bestimmte Elemente eines Interators.
Nein, das hast du missverstanden. itertools.islice(...) erzeugt ein Objekt. Dieses ist ein Iterator. In Python bedeutet das nichts anderes, als dass es ein bestimmtes Protokoll implementiert, dh. bestimmte Attribute bzw. Methoden, die ein bestimmtes Verhalten an den Tag legen. Die Methode next() zB. wirft die Exception StopIteration, wenn sie kein nächstes Element mehr liefern kann. Das for-Statement "kennt" dieses Protokoll und benutzt es entsprechend. Die for-Schleife:

Code: Alles auswählen

for each in seq:
    # ...
macht letztlich nichts anderes als dieser Code:

Code: Alles auswählen

_iter = seq.iter()
while True:
    try:
        each = _iter.next()
    except StopIteration:
        break
    # ...
Das Iterator-Protokoll wird hier beschrieben. Files implementieren dieses Protokoll, deswegen kann man mit for zeilenweise über sie iterieren. Genauso kann man über itertools.islice-Objekte iterieren, weil sie dasselbe Protokoll implementieren. Ohne zu iterieren kommst du aber nicht an die Elemente eines Iterators. Mit print endfinal wird eine String-Repräsentation des Iterator-Objekts endfinal selbst ausgegeben, aber nicht eine seiner Elemente. Was du hier fälschlicherweise erwartet hast, ist vergleichbar damit, dass du eine Druckmaschine anschaust, um zu wissen, was in der Zeitung steht, die sie druckt.

HTH,
Mick.