Ich habe eine Liste von 20 Dateinamen, wie ['file1.txt', 'file2.txt', ...]
. Ich möchte ein Python-Skript schreiben, um diese Dateien zu einer neuen Datei zu verketten. Ich könnte jede Datei durch öffnen f = open(...)
, Zeile für Zeile durch Aufrufen lesen f.readline()
und jede Zeile in diese neue Datei schreiben. Es scheint mir nicht sehr "elegant" zu sein, besonders der Teil, in dem ich Zeile für Zeile lesen / schreiben muss.
Gibt es eine "elegantere" Möglichkeit, dies in Python zu tun?
python
file-io
concatenation
JJ Beck
quelle
quelle
cat file1.txt file2.txt file3.txt ... > output.txt
. Wenn Sie in Python nicht mögenreadline()
, gibt es immerreadlines()
oder einfachread()
.cat file1.txt file2.txt file3.txt
Befehl einfach mit demsubprocess
Modul aus und Sie sind fertig. Ich bin mir aber nicht sicher, ob escat
in Windows funktioniert.with
Anweisung, um sicherzustellen, dass Ihre Dateien ordnungsgemäß geschlossen sind, und durchlaufen Sie die Datei, um Zeilen abzurufen, anstatt sie zu verwendenf.readline()
.Antworten:
Das sollte es tun
Für große Dateien:
Für kleine Dateien:
… Und noch eine interessante, an die ich gedacht habe :
Leider hinterlässt diese letzte Methode einige offene Dateideskriptoren, um die sich der GC sowieso kümmern sollte. Ich fand es nur interessant
quelle
Verwenden Sie
shutil.copyfileobj
.Es liest automatisch die Eingabedateien Stück für Stück für Sie, was effizienter ist und die Eingabedateien einliest und auch dann funktioniert, wenn einige der Eingabedateien zu groß sind, um in den Speicher zu passen:
quelle
for i in glob.glob(r'c:/Users/Desktop/folder/putty/*.txt'):
Nun, ich habe die for-Anweisung ersetzt, um alle Dateien in das Verzeichnis aufzunehmen, aber meineoutput_file
begann in sehr kurzer Zeit sehr groß zu werden, wie in 100 GB.Genau dafür ist Fileinput gedacht :
Für diesen Anwendungsfall ist es nicht viel einfacher, als nur manuell über die Dateien zu iterieren. In anderen Fällen ist es jedoch sehr praktisch, einen einzigen Iterator zu haben, der über alle Dateien iteriert, als wären sie eine einzelne Datei. (Auch die Tatsache, dass
fileinput
jede Datei geschlossen wird, sobald sie fertig ist, bedeutet, dass keinewith
oder jede Datei erforderlich istclose
, aber das ist nur eine einzeilige Einsparung, keine so große Sache.)Es gibt noch einige andere nützliche Funktionen
fileinput
, z. B. die Möglichkeit, Dateien direkt durch Filtern jeder Zeile zu ändern.Wie in den Kommentaren erwähnt und in einem anderen Beitrag besprochen ,
fileinput
funktioniert Python 2.7 nicht wie angegeben. Hier geringfügige Änderungen, um den Code Python 2.7-kompatibel zu machenquelle
fileinput
wird gesagt, dass es eine Möglichkeit ist, eine einfachesys.argv
(oder was als Argumente nachoptparse
/ etc. Zurückbleibt ) in eine große virtuelle Datei für triviale Skripte umzuwandeln und nicht daran zu denken, sie für irgendetwas zu verwenden sonst (dh wenn die Liste keine Befehlszeilenargumente enthält). Oder sie lernen, aber vergessen dann - ich entdecke es jedes oder jedesfor line in fileinput.input()
ist in diesem speziellen Fall nicht die beste Wahl: Das OP möchte Dateien verketten und nicht zeilenweise lesen, was theoretisch ein längerer Prozess istIch weiß nichts über Eleganz, aber das funktioniert:
quelle
cat
kann eine Liste von Dateien erstellt werden, sodass Sie sie nicht wiederholt aufrufen müssen. Sie können es einfach sicher machen, indem Siesubprocess.check_call
stattos.system
Was ist los mit UNIX-Befehlen? (vorausgesetzt, Sie arbeiten nicht unter Windows):
ls | xargs cat | tee output.txt
erledigt den Job (Sie können ihn von Python mit Unterprozess aufrufen, wenn Sie möchten)quelle
cat * | tee output.txt
.cat file1.txt file2.txt | tee output.txt
1> /dev/null
am Ende des BefehlsEin einfacher Benchmark zeigt, dass das Shutil eine bessere Leistung erbringt.
quelle
Eine Alternative zur @ inspectorG4dget-Antwort (beste Antwort bis zum 29.03.2016). Ich habe mit 3 Dateien von 436MB getestet.
@ inspectorG4dget Lösung: 162 Sekunden
Die folgende Lösung: 125 Sekunden
Die Idee ist, eine Batch-Datei zu erstellen und auszuführen, wobei die "alte gute Technologie" genutzt wird. Seine Halbpython arbeitet aber schneller. Funktioniert für Windows.
quelle
Wenn sich viele Dateien im Verzeichnis befinden, ist es
glob2
möglicherweise besser, eine Liste mit Dateinamen zu erstellen, als sie manuell zu schreiben.quelle
Überprüfen Sie die .read () -Methode des File-Objekts:
http://docs.python.org/2/tutorial/inputoutput.html#methods-of-file-objects
Sie könnten so etwas tun wie:
oder eine "elegantere" Python-Art:
was laut diesem Artikel: http://www.skymind.com/~ocrow/python_string/ auch am schnellsten wäre.
quelle
Wenn die Dateien nicht gigantisch sind:
Wenn die Dateien zu groß sind, um vollständig gelesen und im RAM gespeichert zu werden, muss der Algorithmus etwas anders sein, um jede Datei zu lesen, die
read(10000)
beispielsweise von Blöcken fester Länge in einer Schleife kopiert werden soll .quelle
os.open
und verwendenos.read
, da plainopen
Pythons Wrapper um Cs stdio verwendet, was bedeutet, dass entweder 1 oder 2 zusätzliche Puffer im Weg sind.quelle
quelle