Writelines schreibt Zeilen ohne Zeilenumbruch. Füllt einfach die Datei

75

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)
user836087
quelle
Es scheint, als würden Sie "\n"nirgendwo in Ihrem Bereich anhängen line_list.
Rohit Jain
2
Sie könnten einen Blick auf csv
esauro
Wo füge ich das "\ n" hinzu? Füge ich es dem Listenobjekt hinzu?
user836087

Antworten:

56

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 fwFolgendes 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:

fw.writelines(line_list)

Du machst das:

cw.writerows(row_list)

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 den openganzen Weg zum anderen Ende des Programms verschoben haben write, haben Sie so ziemlich alle Vorteile verloren -auf einmal.)

abarnert
quelle
41
all dies, weil Python nicht das Offensichtliche tut mitwritelines
StephenBoesch
28
Beeindruckend. Dies ist ein lächerliches Verhalten von Python: readlines () sollte Zeilenumbrüche entfernen, aber nicht, und writelines () sollten Zeilenumbrüche hinzufügen , aber nicht. Der springende Punkt beim Lesen und Schreiben von Zeilen ist, dass Sie Listen leicht lesen und schreiben können. Leicht wütend!
James
6
Lohnt sich ein PEP wie f.writelines (lines, end = '\ n')?
John Lin
sollte im zweiten Beispiel fw.writelines (Zeile + '\ n' für Zeile in line_list) sein
Dan
46

Die Dokumentation fürwritelines() Staaten:

writelines() fügt keine Zeilentrennzeichen hinzu

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.

Greg Hewgill
quelle
+1. Dies ist die einfachste und mit ziemlicher Sicherheit am besten geeignete Lösung, wenn das OP nicht auf eine höhere Ebene wie wechseln möchte csv.
Abarnert
82
Was für ein schrecklicher Name für die Funktion, nur um "passende" Readlines zu erhalten.
Sandy Chapman
21
schlimmer als schrecklicher Name: schreckliche Funktionalität
StephenBoesch
22

Wie andere angemerkt haben, writelineshandelt 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)
Brent Faust
quelle
8

writelines()fügt keine Zeilentrennzeichen hinzu. Sie können die Liste der Zeichenfolgen ändern, indem Sie am Ende jeder Zeichenfolge map()einen neuen \n(Zeilenumbruch) hinzufügen .

items = ['abc', '123', '!@#']
items = map(lambda x: x + '\n', items)
w.writelines(items)
Jossef Harush
quelle
2

Wie andere bereits erwähnt haben und entgegen dem, was der Methodenname bedeuten würde, werden writelineskeine 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!

jtschoonhoven
quelle
1

Wie wir hier gut etabliert haben, werden writelinesdie 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 wird readlines()und der erste Lesevorgang die Zeilenumbrüche durchhielt!

Wenn Sie eine Datei zum Lesen im Binärmodus (via 'rb') öffnen und dann verwenden readlines(), 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 wahrscheinlich writelinesnichts 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.

BuvinJ
quelle
Und wann genau möchten Sie eine Datei lesen, um sie zurückzuschreiben?
Privat
1
Sie nehmen das Codebeispiel viel zu wörtlich. Ich habe keinen falschen Kontext und keinen fremden Beispielcode eingefügt, wenn Sie eine Datei lesen und zurückschreiben würden. Normalerweise liegt etwas dazwischen, wo Sie den Inhalt ändern würden. Oder Sie "kopieren" / optimieren eine Quelldatei in eine Zieldatei. Der Punkt ist, dass die Gegenstücke zu Readlines / Writelines dieses Problem implizit behandeln.
BuvinJ
Entschuldigung, ich wollte nicht auf dem Thema bestehen. Es ist nur so, dass die meiste Zeit, wenn ich eine Datei lese und in sie oder in eine andere Datei zurückschreibe, eine der Methoden, die ich .stripaufrufe, oder '.rstrip ()' ist. In meinem Workflow würde dies einfach nie vorkommen.
Privat
Np. Ich habe oft das Gleiche getan, aber wenn Sie auf dieser Seite gelandet sind, möchten Sie diese Vorgehensweise möglicherweise in einigen Anwendungsfällen ändern, in denen Sie die Zeilenenden beibehalten möchten. Sie können vermeiden, dass Sie sie explizit anhängen müssen, indem Sie diesen Beitrag berücksichtigen .
BuvinJ
1

Da wir nur Zeilen trennen möchten und die writelinesFunktion 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.

Hosein Basafa
quelle
Da Sie eine Antwort auf eine ältere Frage veröffentlichen, ist es äußerst hilfreich, dass Sie Ihre angebliche Antwort mit etwas Code und der Ausgabe unterstützen, die sich aus der Verwendung Ihres Codes ergibt.
Grauer
-4

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")
Docuemada
quelle