Ich muss der ersten Zeile einer Textdatei eine einzelne Zeile hinzufügen, und es sieht so aus, als ob mir nur mehr Codezeilen zur Verfügung stehen, als ich von Python erwarten würde. Etwas wie das:
f = open('filename','r')
temp = f.read()
f.close()
f = open('filename', 'w')
f.write("#testfirstline")
f.write(temp)
f.close()
Gibt es keinen einfacheren Weg? Außerdem sehe ich dieses Beispiel mit zwei Handles häufiger als das Öffnen eines einzelnen Handles zum Lesen und Schreiben ('r +') - warum ist das so?
Antworten:
Python macht viele Dinge einfach und enthält Bibliotheken und Wrapper für viele gängige Operationen, aber das Ziel ist nicht, grundlegende Wahrheiten zu verbergen.
Die grundlegende Wahrheit, auf die Sie hier stoßen, ist, dass Sie einer vorhandenen flachen Struktur im Allgemeinen keine Daten voranstellen können, ohne die gesamte Struktur neu zu schreiben. Dies gilt unabhängig von der Sprache.
Es gibt Möglichkeiten, ein Dateihandle zu speichern oder Ihren Code weniger lesbar zu machen. Viele davon sind in anderen Antworten enthalten, aber nichts ändert die grundlegende Operation: Sie müssen die vorhandene Datei einlesen und dann die Daten ausschreiben, die Sie voranstellen möchten, gefolgt von die vorhandenen Daten, die Sie einlesen.
Sparen Sie sich auf jeden Fall das Dateihandle, aber versuchen Sie nicht, diesen Vorgang in so wenige Codezeilen wie möglich zu packen. Suchen Sie niemals nach den wenigsten Codezeilen - das ist Verschleierung, nicht Programmierung.
quelle
Ich würde mich an getrennte Lese- und Schreibvorgänge halten, aber wir können sie sicherlich präziser ausdrücken:
Python2:
with file('filename', 'r') as original: data = original.read() with file('filename', 'w') as modified: modified.write("new first line\n" + data)
Python3:
with open('filename', 'r') as original: data = original.read() with open('filename', 'w') as modified: modified.write("new first line\n" + data)
Hinweis: Die Funktion file () ist in Python3 nicht verfügbar.
quelle
file()
-Funktion nicht in Python 3 verfügbar ist, sondern nur in Version 2. Ersetzen Sie sie einfach durchopen()
Python 3.open()
Funktion in Python öffnen . Die Dateifunktion ist nur aus historischen Gründen vorhanden.file
intuitiver, unabhängig von Community-Konsens und gemeinsamen Stilrichtlinien. Aber als 3.x kam (und ich war ein ziemlich eifriger FWIW-Anwender), hatte ich keine Wahl mehr :)Anderer Ansatz:
with open("infile") as f1: with open("outfile", "w") as f2: f2.write("#test firstline") for line in f1: f2.write(line)
oder ein Einzeiler:
open("outfile", "w").write("#test firstline\n" + open("infile").read())
Vielen Dank für die Gelegenheit, über dieses Problem nachzudenken :)
Prost
quelle
with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)
quelle
Sie können einen Schreibaufruf damit speichern:
f.write('#testfirstline\n' + temp)
Wenn Sie 'r +' verwenden, müssen Sie die Datei nach dem Lesen und vor dem Schreiben zurückspulen.
quelle
f.write('#testfirstline\n' + temp)
f.writelines(('#testfirstline\n',tmp))
. Wenn dann die Temperatur sehr hoch ist, erstellen Sie keine weitere große Zeichenfolge, um dies alles aufzuschreiben. Oder verwenden Sie einfach die zusätzliche Schreibzeile wie im OP ...Hier ist ein 3-Liner, den ich für klar und flexibel halte. Es verwendet die Funktion list.insert. Wenn Sie der Datei also wirklich voranstellen möchten, verwenden Sie l.insert (0, 'insert_str'). Als ich dies tatsächlich für ein Python-Modul tat, das ich entwickle, habe ich l.insert (1, 'insert_str') verwendet, weil ich die Zeichenfolge '# - - encoding: utf-8 - -' in Zeile 0 überspringen wollte der Code.
f = open(file_path, 'r'); s = f.read(); f.close() l = s.splitlines(); l.insert(0, 'insert_str'); s = '\n'.join(l) f = open(file_path, 'w'); f.write(s); f.close()
quelle
Dies erledigt den Job, ohne die gesamte Datei in den Speicher einzulesen, obwohl dies unter Windows möglicherweise nicht funktioniert
def prepend_line(path, line): with open(path, 'r') as old: os.unlink(path) with open(path, 'w') as new: new.write(str(line) + "\n") shutil.copyfileobj(old, new)
quelle
shutil.copyfileobj
anstatt sie zu überschreiben?path
beim zweiten Aufruf einfach eine andere einopen
.Eine Möglichkeit ist die folgende:
import os open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read()) os.rename('tempfile', 'filename')
quelle
Wenn Sie der Datei nach einem bestimmten Text ein Präfix voranstellen möchten, können Sie die folgende Funktion verwenden.
def prepend_text(file, text, after=None): ''' Prepend file with given raw text ''' f_read = open(file, 'r') buff = f_read.read() f_read.close() f_write = open(file, 'w') inject_pos = 0 if after: pattern = after inject_pos = buff.find(pattern)+len(pattern) f_write.write(buff[:inject_pos] + text + buff[inject_pos:]) f_write.close()
Zuerst öffnen Sie die Datei, lesen sie und speichern sie in einer Zeichenfolge. Dann versuchen wir, die Zeichennummer in der Zeichenfolge zu finden, in die die Injektion erfolgen soll. Dann können wir mit einem einzigen Schreibvorgang und einer intelligenten Indizierung der Zeichenfolge die gesamte Datei einschließlich des eingefügten Textes neu schreiben.
quelle
Sehe ich etwas nicht oder könnten wir nicht einfach einen Puffer verwenden, der groß genug ist, um die Eingabedatei in Teilen (anstelle des gesamten Inhalts) einzulesen, und mit diesem Puffer die Datei durchlaufen, während sie geöffnet ist, und die Datei weiter austauschen <- > Pufferinhalt?
Dies scheint viel effizienter zu sein (insbesondere für große Dateien), als den gesamten Inhalt im Speicher zu lesen , ihn im Speicher zu ändern und ihn in dieselbe oder (noch schlimmer) in eine andere Datei zurückzuschreiben. Es tut mir leid, dass ich jetzt keine Zeit habe, ein Beispiel-Snippet zu implementieren. Ich werde später darauf zurückkommen, aber vielleicht haben Sie die Idee.
quelle