Nochmal kurz, Inhalt mehrerer Dateien in eine Datei tun

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
ratna_fong
User
Beiträge: 38
Registriert: Samstag 3. Juli 2010, 10:43

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:
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Du möchtest enumerate oder itertools.islice verwenden.
Das Leben ist wie ein Tennisball.
ratna_fong
User
Beiträge: 38
Registriert: Samstag 3. Juli 2010, 10:43

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:
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

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)
In specifications, Murphy's Law supersedes Ohm's.
ratna_fong
User
Beiträge: 38
Registriert: Samstag 3. Juli 2010, 10:43

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
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
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.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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° ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
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()`. ;-)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

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 :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

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.
In specifications, Murphy's Law supersedes Ohm's.
Antworten