Schreiben einer Liste in eine Datei mit Python

672

Ist dies der sauberste Weg, eine Liste in eine Datei zu schreiben, da writelines()keine Zeilenumbrüche eingefügt werden?

file.writelines(["%s\n" % item  for item in list])

Es scheint, als gäbe es einen Standardweg ...

Josh Arenberg
quelle
37
Beachten Sie, dass writelineskeine Zeilenumbrüche hinzugefügt werden, da diese gespiegelt werden readlinesund diese auch nicht entfernt werden.
SingleNegationElimination

Antworten:

908

Sie können eine Schleife verwenden:

with open('your_file.txt', 'w') as f:
    for item in my_list:
        f.write("%s\n" % item)

In Python 2 können Sie auch verwenden

with open('your_file.txt', 'w') as f:
    for item in my_list:
        print >> f, item

Wenn Sie an einem einzelnen Funktionsaufruf interessiert sind, entfernen Sie mindestens die eckigen Klammern [], damit die zu druckenden Zeichenfolgen einzeln erstellt werden (ein Genexp anstelle eines Listcomp) - kein Grund, den gesamten erforderlichen Speicher zu belegen die gesamte Liste der Zeichenfolgen zu materialisieren.

Alex Martelli
quelle
7
Dies ist nicht besonders komplex, aber warum nicht einfach Pickle oder JSON verwenden, damit Sie sich nicht um die Serialisierung und Deserialisierung kümmern müssen?
Jason Baker
82
Zum Beispiel, weil Sie eine Ausgabetextdatei möchten, die mit einem Element pro Zeile leicht gelesen, bearbeitet usw. werden kann. Kaum ein seltener Wunsch ;-).
Alex Martelli
1
Ich fand, dass das \ n im ersten unter Python 2.7 / Windows
Jorge Rodriguez
11
Dies wird ein zusätzliches Zeilenumbruchzeichen am Ende schreiben ... anstatt einer Schleife könnten Sie einfach schreibenthefile.write('\n'.join(thelist))
Tgsmith61591
3
Ich würde hinzufügen: "Seien Sie vorsichtig mit dem Listendatentyp". Ich habe einige seltsame Ergebnisse erzielt, vielleicht kann dies jemandem helfen:thefile.write(str(item) + "\n")
iipr
383

Was machst du mit der Datei? Existiert diese Datei für Menschen oder andere Programme mit klaren Interoperabilitätsanforderungen?

Wenn Sie nur versuchen, eine Liste zur späteren Verwendung durch dieselbe Python-App auf die Festplatte zu serialisieren, sollten Sie die Liste auswählen .

import pickle

with open('outfile', 'wb') as fp:
    pickle.dump(itemlist, fp)

Um es zurückzulesen:

with open ('outfile', 'rb') as fp:
    itemlist = pickle.load(fp)
SingleNegationElimination
quelle
35
+1 - Warum das Rad neu erfinden, wenn in Python die Serialisierung integriert ist?
Jason Baker
20
+1 - outfile ist so etwas wie: open( "save.p", "wb" ) infile ist so etwas wie:open( "save.p", "rb" )
xxjjnn
2
Das Problem ist, dass die Liste in den Speicher passen muss. Wenn dies nicht der Fall ist, ist Zeile für Zeile in der Tat eine mögliche Strategie (oder eine Alternative wie in stackoverflow.com/questions/7180212/… )
Filippo Mazza
1
Verwenden Sie in Python 2 'r' anstelle von 'rb', wenn Sie die Pickle lesen, wenn Sie den "ValueError: Unsure String Pickle" erhalten
Warteschlange
1
@serafeim: nein; Der with:Block schließt die Datei, bevor mit der nächsten Anweisung außerhalb des withBlocks fortgefahren wird.
SingleNegationElimination
285

Der einfachere Weg ist:

with open("outfile", "w") as outfile:
    outfile.write("\n".join(itemlist))

Sie können mithilfe eines Generatorausdrucks sicherstellen, dass alle Elemente in der Elementliste Zeichenfolgen sind:

with open("outfile", "w") as outfile:
    outfile.write("\n".join(str(item) for item in itemlist))

Denken Sie daran, dass sich alle itemlistListen im Speicher befinden müssen. Achten Sie daher auf den Speicherverbrauch.

Osantana
quelle
23
Kein nachfolgender Zeilenumbruch, verwendet im Vergleich zur Schleife 2x Leerzeichen.
Dave
7
Die erste Frage, die sich stellt, ist natürlich, ob das OP es benötigt, um in einer neuen Zeile zu enden, und ob der Platzbedarf wichtig ist oder nicht. Sie wissen, was sie über vorzeitige Optimierungen sagen.
Jason Baker
15
Ein Nachteil: Hiermit wird der gesamte Inhalt der Datei im Speicher erstellt, bevor eine davon ausgeschrieben wird. Daher kann die maximale Speichernutzung hoch sein.
RobM
4
Ich kann das nie zum Laufen bringen. Ich erhalte die folgende Fehlermeldung: "text = '\ n'.join (namelist) +' \ n 'TypeError: Sequenzelement 0: erwartete Zeichenfolge, Liste gefunden"
Dan
2
Sie müssen sicherstellen, dass alle Elemente in der Namensliste Zeichenfolgen sind.
Osantana
94

Verwenden der Syntax von Python 3 und Python 2.6+ :

with open(filepath, 'w') as file_handler:
    for item in the_list:
        file_handler.write("{}\n".format(item))

Dies ist plattformunabhängig. Außerdem wird die letzte Zeile mit einem Zeilenumbruchzeichen abgeschlossen. Dies ist eine bewährte Methode für UNIX .

Ab Python 3.6 "{}\n".format(item)kann durch einen F-String ersetzt werden : f"{item}\n".

Orluke
quelle
Ich möchte nicht "\ n" für das letzte Element hinzufügen. Was tun? Ich will nicht, wenn Bedingung
pyd
4
@pyd Ersetzen Sie die for-Schleife durchfile_handler.write("\n".join(str(item) for item in the_list))
orluke
88

Noch ein anderer Weg. Serialisieren Sie mit simplejson zu json ( in Python 2.6 als json enthalten ):

>>> import simplejson
>>> f = open('output.txt', 'w')
>>> simplejson.dump([1,2,3,4], f)
>>> f.close()

Wenn Sie output.txt untersuchen:

[1, 2, 3, 4]

Dies ist nützlich, da die Syntax pythonisch ist, von Menschen gelesen werden kann und von anderen Programmen in anderen Sprachen gelesen werden kann.

Jason Baker
quelle
39

Ich dachte, es wäre interessant, die Vorteile der Verwendung eines Genexp zu untersuchen. Hier ist meine Meinung.

Das Beispiel in der Frage verwendet eckige Klammern, um eine temporäre Liste zu erstellen. Dies entspricht:

file.writelines( list( "%s\n" % item for item in list ) )

Dadurch wird unnötig eine temporäre Liste aller Zeilen erstellt, die ausgeschrieben werden. Dies kann je nach Größe Ihrer Liste und der Ausführlichkeit der Ausgabe erhebliche Speichermengen beanspruchen str(item).

Wenn Sie die eckigen Klammern entfernen (entspricht dem Entfernen des list()obigen Wrapping- Aufrufs), wird stattdessen ein temporärer Generator an Folgendes übergebenfile.writelines() :

file.writelines( "%s\n" % item for item in list )

Dieser Generator erstellt bei Bedarf eine Newline-terminierte Darstellung Ihrer itemObjekte (dh wie sie ausgeschrieben sind). Das ist aus mehreren Gründen schön:

  • Der Speicheraufwand ist selbst bei sehr großen Listen gering
  • Wenn str(item)es langsam ist, gibt es sichtbaren Fortschritt in der Datei, während jedes Element verarbeitet wird

Dies vermeidet Speicherprobleme wie:

In [1]: import os

In [2]: f = file(os.devnull, "w")

In [3]: %timeit f.writelines( "%s\n" % item for item in xrange(2**20) )
1 loops, best of 3: 385 ms per loop

In [4]: %timeit f.writelines( ["%s\n" % item for item in xrange(2**20)] )
ERROR: Internal Python error in the inspect module.
Below is the traceback from this internal error.

Traceback (most recent call last):
...
MemoryError

(Ich habe diesen Fehler ausgelöst, indem ich Pythons maximalen virtuellen Speicher auf ~ 100 MB mit begrenzt habe ulimit -v 102400).

Wenn Sie die Speichernutzung beiseite lassen, ist diese Methode nicht schneller als das Original:

In [4]: %timeit f.writelines( "%s\n" % item for item in xrange(2**20) )
1 loops, best of 3: 370 ms per loop

In [5]: %timeit f.writelines( ["%s\n" % item for item in xrange(2**20)] )
1 loops, best of 3: 360 ms per loop

(Python 2.6.2 unter Linux)

RobM
quelle
20

Weil ich faul bin....

import json
a = [1,2,3]
with open('test.txt', 'w') as f:
    f.write(json.dumps(a))

#Now read the file back into a Python list object
with open('test.txt', 'r') as f:
    a = json.loads(f.read())
CommandoScorch
quelle
Sind Listen json serialisierbar?
KRazzy R
1
Ja, das sind sie!
CommandoScorch
1
import json; test_list = [1,2,3]; list_as_a_string = json.dumps (test_list); #list_as_a_string ist jetzt die Zeichenfolge '[1,2,3]'
CommandoScorch
Ich mache das with open ('Sp1.txt', 'a') as outfile: json.dump (sp1_segments, outfile) logger.info ("Saved sp_1 segments"); Das Problem ist, dass mein Programm dreimal ausgeführt wird und die Ergebnisse von drei Läufen zusammengeführt werden. Gibt es eine Möglichkeit, 1-2 leere Zeilen hinzuzufügen, damit die Ergebnisse aus jedem Lauf erkennbar sind?
KRazzy R
1
Absolut! könnten Sie stattdessen tun json.dump(sp1_segments + "\n\n", outfile)?
CommandoScorch
19

Serialisieren Sie die Liste in eine Textdatei mit einem durch Kommas getrennten Wert

mylist = dir()
with open('filename.txt','w') as f:
    f.write( ','.join( mylist ) )
themadmax
quelle
14

Allgemein

Es folgt die Syntax für die Methode writelines ()

fileObject.writelines( sequence )

Beispiel

#!/usr/bin/python

# Open a file
fo = open("foo.txt", "rw+")
seq = ["This is 6th line\n", "This is 7th line"]

# Write sequence of lines at the end of the file.
line = fo.writelines( seq )

# Close opend file
fo.close()

Referenz

http://www.tutorialspoint.com/python/file_writelines.htm

Marvin W.
quelle
13
file.write('\n'.join(list))
mtasic85
quelle
1
Man sollte beachten, dass dies erfordert, dass die Datei als Text geöffnet wird, um wirklich plattformneutral zu sein.
Jason Baker
2
Wie bekommt man die fileVariable?
Jonathan Morales Vélez
8
with open ("test.txt","w")as fp:
   for line in list12:
       fp.write(line+"\n")
Shankar
quelle
7

Sie können die Druckfunktion auch wie folgt verwenden, wenn Sie sich in Python3 befinden.

f = open("myfile.txt","wb")
print(mylist, file=f)
Nandita Damaraju
quelle
ist es nicht nur eine Zeile in myfile.txt, so etwas wie: ['a', 'b', 'c'] anstatt jedes a, b, c in jede Zeile zu schreiben.
Harry Duong
3

Warum versuchst du es nicht?

file.write(str(list))
Bob
quelle
2

Diese Logik konvertiert zuerst die Elemente in der Liste in string(str). Manchmal enthält die Liste ein Tupel wie

alist = [(i12,tiger), 
(113,lion)]

Diese Logik schreibt, um jedes Tupel in einer neuen Zeile abzulegen. Wir können später evalbeim Laden jedes Tupels beim Lesen der Datei Folgendes verwenden:

outfile = open('outfile.txt', 'w') # open a file in write mode
for item in list_to_persistence:    # iterate over the list items
   outfile.write(str(item) + '\n') # write to the file
outfile.close()   # close the file 
Tahir Ahmad
quelle
1

Eine andere Möglichkeit zum Iterieren und Hinzufügen von Zeilenumbrüchen:

for item in items:
    filewriter.write(f"{item}" + "\n")
Alex
quelle
0

In Python> 3 können Sie printund *zum Entpacken von Argumenten verwenden:

with open("fout.txt", "w") as fout:
    print(*my_list, sep="\n", file=fout)
Bricoletc
quelle
-2

In Python3 können Sie diese Schleife verwenden

with open('your_file.txt', 'w') as f:
    for item in list:
        f.print("", item)
Nikhil B.
quelle
-3

Sei avg die Liste, dann:

In [29]: a = n.array((avg))
In [31]: a.tofile('avgpoints.dat',sep='\n',dtype = '%f')

Sie können %eoder %sje nach Ihren Anforderungen verwenden.

Belthazar
quelle
-4
poem = '''\
Programming is fun
When the work is done
if you wanna make your work also fun:
use Python!
'''
f = open('poem.txt', 'w') # open for 'w'riting
f.write(poem) # write text to file
f.close() # close the file

So funktioniert es: Öffnen Sie zunächst eine Datei, indem Sie die integrierte Öffnungsfunktion verwenden und den Namen der Datei sowie den Modus angeben, in dem die Datei geöffnet werden soll. Der Modus kann ein Lesemodus ('r'), ein Schreibmodus ('w') oder ein Anhänge-Modus ('a') sein. Wir können auch angeben, ob wir im Textmodus ('t') oder im Binärmodus ('b') lesen, schreiben oder anhängen. Es gibt tatsächlich viel mehr Modi und die Hilfe (offen) gibt Ihnen mehr Details darüber. Standardmäßig betrachtet open () die Datei als 't'ext-Datei' und öffnet sie im 'r'ead-Modus. In unserem Beispiel öffnen wir zuerst die Datei im Schreibtextmodus und verwenden die Schreibmethode des Dateiobjekts, um in die Datei zu schreiben. Anschließend schließen wir die Datei endgültig.

Das obige Beispiel stammt aus dem Buch "A Byte of Python" von Swaroop C H. swaroopch.com

vayah
quelle
5
Dies schreibt eine Zeichenfolge in eine Datei, nicht eine Liste (von Zeichenfolgen), wie das OP fragt
gwideman