Ich habe ein Programm, das eine Liste in eine Datei schreibt. Die Liste ist eine Liste von durch Pipe getrennten Zeilen, und die Zeilen sollten wie folgt in die Datei geschrieben werden:
123|GSV|Weather_Mean|hello|joe|43.45
122|GEV|temp_Mean|hello|joe|23.45
124|GSI|Weather_Mean|hello|Mike|47.45
ABER es schrieb ihnen Zeile dieses ahhhh:
123|GSV|Weather_Mean|hello|joe|43.45122|GEV|temp_Mean|hello|joe|23.45124|GSI|Weather_Mean|hello|Mike|47.45
Dieses Programm hat alle Zeilen wie eine Zeile ohne Zeilenumbrüche geschrieben. Das tut mir sehr weh und ich muss herausfinden, wie ich das umkehren kann, aber wo ist mein Programm hier falsch? Ich dachte, Schreibzeilen sollten Zeilen in die Datei schreiben, anstatt alles in eine Zeile zu schreiben.
fr = open(sys.argv[1], 'r') # source file
fw = open(sys.argv[2]+"/masked_"+sys.argv[1], 'w') # Target Directory Location
for line in fr:
line = line.strip()
if line == "":
continue
columns = line.strip().split('|')
if columns[0].find("@") > 1:
looking_for = columns[0] # this is what we need to search
else:
looking_for = "[email protected]"
if looking_for in d:
# by default, iterating over a dictionary will return keys
new_line = d[looking_for]+'|'+'|'.join(columns[1:])
line_list.append(new_line)
else:
new_idx = str(len(d)+1)
d[looking_for] = new_idx
kv = open(sys.argv[3], 'a')
kv.write(looking_for+" "+new_idx+'\n')
kv.close()
new_line = d[looking_for]+'|'+'|'.join(columns[1:])
line_list.append(new_line)
fw.writelines(line_list)
"\n"
nirgendwo in Ihrem Bereich anhängenline_list
.Antworten:
Dies ist tatsächlich ein ziemlich häufiges Problem für Python-Neulinge - insbesondere, da in der Standardbibliothek und in beliebten Bibliotheken von Drittanbietern einige Lesefunktionen Zeilenumbrüche entfernen, diese jedoch fast nicht durch Schreibfunktionen (mit Ausnahme der zugehörigen Funktionen
log
) hinzugefügt werden.Es gibt also eine Menge Python-Code, der Dinge wie:
fw.write('\n'.join(line_list) + '\n')
oder
fw.write(line + '\n' for line in line_list)
Beides ist richtig, und natürlich können Sie sogar Ihre eigenen WritelinesWithNewlines-Funktionen schreiben, die es abschließen…
Sie sollten dies jedoch nur tun, wenn Sie es nicht vermeiden können.
Es ist besser, wenn Sie die Zeilenumbrüche überhaupt erstellen / beibehalten können - wie in Greg Hewgills Vorschlägen:
line_list.append(new_line + "\n")
Und es ist noch besser, wenn Sie auf einer höheren Ebene als rohe Textzeilen arbeiten können, z. B. indem Sie das CSV- Modul in der Standardbibliothek verwenden, wie esuaro vorschlägt.
Zum Beispiel können Sie direkt nach dem Definieren
fw
Folgendes tun:cw = csv.writer(fw, delimiter='|')
Dann stattdessen:
new_line = d[looking_for]+'|'+'|'.join(columns[1:]) line_list.append(new_line)
Du machst das:
row_list.append(d[looking_for] + columns[1:])
Und am Ende stattdessen:
Du machst das:
Schließlich lautet Ihr Entwurf "Öffnen Sie eine Datei, erstellen Sie eine Liste von Zeilen, die der Datei hinzugefügt werden sollen, und schreiben Sie sie dann alle auf einmal". Wenn Sie die Datei oben öffnen möchten, schreiben Sie die Zeilen einfach nacheinander. Unabhängig davon, ob Sie einfache Schreibvorgänge oder a verwenden
csv.writer
, wird dies Ihr Leben einfacher und Ihren Code leichter lesbar machen. (Manchmal kann es Gründe für Einfachheit, Effizienz oder Korrektheit geben, eine Datei auf einmal zu schreiben - aber wenn Sie denopen
ganzen Weg zum anderen Ende des Programms verschoben habenwrite
, haben Sie so ziemlich alle Vorteile verloren -auf einmal.)quelle
writelines
Die Dokumentation für
writelines()
Staaten:Sie müssen sie also selbst hinzufügen. Zum Beispiel:
line_list.append(new_line + "\n")
wann immer Sie ein neues Element anhängen
line_list
.quelle
csv
.Wie andere angemerkt haben,
writelines
handelt es sich um eine Fehlbezeichnung (es werden lächerlich keine Zeilenumbrüche am Ende jeder Zeile hinzugefügt).Fügen Sie dazu explizit jede Zeile hinzu:
with open(dst_filename, 'w') as f: f.writelines(s + '\n' for s in lines)
quelle
writelines()
fügt keine Zeilentrennzeichen hinzu. Sie können die Liste der Zeichenfolgen ändern, indem Sie am Ende jeder Zeichenfolgemap()
einen neuen\n
(Zeilenumbruch) hinzufügen .items = ['abc', '123', '!@#'] items = map(lambda x: x + '\n', items) w.writelines(items)
quelle
Wie andere bereits erwähnt haben und entgegen dem, was der Methodenname bedeuten würde, werden
writelines
keine Zeilentrennzeichen hinzugefügt. Dies ist ein Lehrbuchfall für einen Generator. Hier ist ein erfundenes Beispiel:def item_generator(things): for item in things: yield item yield '\n' def write_things_to_file(things): with open('path_to_file.txt', 'wb') as f: f.writelines(item_generator(things))
Vorteile: Fügt Zeilenumbrüche explizit hinzu, ohne die Eingabe- oder Ausgabewerte zu ändern oder eine unordentliche Verkettung von Zeichenfolgen vorzunehmen. Und schafft kritisch keine neuen Datenstrukturen im Speicher. IO (Schreiben in eine Datei) ist, wenn solche Dinge tatsächlich eine Rolle spielen. Hoffe das hilft jemandem!
quelle
Wie wir hier gut etabliert haben, werden
writelines
die Zeilenumbrüche nicht für Sie angehängt. Aber was jeder zu vermissen scheint, ist, dass es nicht muss, wenn es als direktes "Gegenstück" für verwendet wirdreadlines()
und der erste Lesevorgang die Zeilenumbrüche durchhielt!Wenn Sie eine Datei zum Lesen im Binärmodus (via
'rb'
) öffnen und dann verwendenreadlines()
, um den Dateiinhalt zeilenweise in den Speicher abzurufen, bleiben die Zeilenumbrüche am Ende Ihrer Zeilen hängen! Wenn Sie sie dann anschließend zurückschreiben, möchten Sie wahrscheinlichwritelines
nichts anhängen!Wenn ja, machen Sie so etwas wie:
with open('test.txt','rb') as f: lines=f.readlines() with open('test.txt','wb') as f: f.writelines(lines)
Sie sollten am Ende denselben Dateiinhalt haben, mit dem Sie begonnen haben.
quelle
.strip
aufrufe, oder '.rstrip ()' ist. In meinem Workflow würde dies einfach nie vorkommen.Da wir nur Zeilen trennen möchten und die
writelines
Funktion in Python das Hinzufügen von Trennzeichen zwischen Zeilen nicht unterstützt, habe ich den einfachen Code geschrieben, der am besten zu diesem Problem passt:sep = "\n" # defining the separator new_lines = sep.join(lines) # lines as an iterator containing line strings
und schlussendlich:
with open("file_name", 'w') as file: file.writelines(new_lines)
und du bist fertig.
quelle
Ich bin immer wieder auf diesen Thread gestoßen, als ich versucht habe, ein ähnliches Problem beim Schreiben in Dateien in R zu lösen. Für diejenigen, die das gleiche Problem hatten, ist hier meine Lösung:
List_To_Be_Written_To_File<-sprintf("%s%s",as.character(List_To_Be_Written_To_File),"\n")
quelle