Écrire une liste dans un fichier avec Python

676

Est-ce la façon la plus simple d'écrire une liste dans un fichier, car writelines()n'insère pas de caractères de nouvelle ligne?

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

Il semble qu'il y aurait un moyen standard ...

Josh Arenberg
la source
37
notez que writelinescela n'ajoute pas de nouvelles lignes car il reflète readlines, ce qui ne les supprime pas non plus.
SingleNegationElimination

Réponses:

915

Vous pouvez utiliser une boucle:

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

Dans Python 2, vous pouvez également utiliser

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

Si vous aimez un seul appel de fonction, supprimez au moins les crochets [], de sorte que les chaînes à imprimer soient faites une par une (un genexp plutôt qu'une listcomp) - aucune raison de prendre toute la mémoire requise pour matérialiser toute la liste des chaînes.

Alex Martelli
la source
7
Ce n'est pas terriblement complexe, mais pourquoi ne pas simplement utiliser pickle ou json pour ne pas avoir à vous soucier de la sérialisation et de la désérialisation?
Jason Baker,
82
Par exemple, parce que vous voulez un fichier texte de sortie qui peut être facilement lu, édité, etc., avec un élément par ligne. A peine une envie rare ;-).
Alex Martelli
1
J'ai trouvé que le \ n dans le premier était redondant sur Python 2.7 / Windows
Jorge Rodriguez
11
Cela écrira un caractère de nouvelle ligne supplémentaire à la fin ... plutôt que de boucler, vous pourriez simplement écrirethefile.write('\n'.join(thelist))
Tgsmith61591
3
J'ajouterais: "Soyez prudent avec le type de données de la liste". thefile.write(str(item) + "\n")
J'obtenais
384

Qu'allez-vous faire avec le fichier? Ce fichier existe-t-il pour les humains ou d'autres programmes avec des exigences d'interopérabilité claires?

Si vous essayez simplement de sérialiser une liste sur le disque pour une utilisation ultérieure par la même application python, vous devez décaper la liste.

import pickle

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

Pour le relire:

with open ('outfile', 'rb') as fp:
    itemlist = pickle.load(fp)
SingleNegationElimination
la source
35
+1 - Pourquoi réinventer la roue lorsque Python a intégré la sérialisation?
Jason Baker,
20
+1 - outfile est quelque chose comme: open( "save.p", "wb" ) infile est quelque chose comme:open( "save.p", "rb" )
xxjjnn
2
Le problème est que la liste doit tenir en mémoire. Si ce n'est pas le cas, ligne par ligne est en effet une stratégie possible (ou bien aller avec une alternative comme dans stackoverflow.com/questions/7180212/… )
Filippo Mazza
1
En Python 2, utilisez 'r' au lieu de 'rb' lors de la lecture du pickle si vous obtenez le "ValueError: pick-up de chaîne non sécurisé"
queise
1
@serafeim: non; le with:bloc fermera le fichier avant de passer à l'instruction suivante en dehors du withbloc.
SingleNegationElimination
286

La manière la plus simple est:

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

Vous pouvez vous assurer que tous les éléments de la liste d'éléments sont des chaînes en utilisant une expression de générateur:

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

N'oubliez pas que toute la itemlistliste doit être en mémoire, alors faites attention à la consommation de mémoire.

osantana
la source
23
Pas de retour à la ligne, utilise un espace 2x par rapport à la boucle.
Dave
7
Bien sûr, la première question qui vient à l'esprit est de savoir si le PO doit ou non se terminer dans une nouvelle ligne et si la quantité d'espace est importante ou non. Vous savez ce qu'ils disent des optimisations prématurées.
Jason Baker,
15
Un inconvénient: cela construit l'intégralité du contenu du fichier en mémoire avant de l'écrire, de sorte que l'utilisation maximale de la mémoire peut être élevée.
RobM
4
Je ne pourrai jamais faire fonctionner ça. J'obtiens cette erreur: "text = '\ n'.join (namelist) +' \ n 'TypeError: item de séquence 0: chaîne attendue, liste trouvée"
Dan
2
Vous devez vous assurer que tous les éléments de la «liste de noms» sont des chaînes.
osantana
94

Utilisation de la syntaxe Python 3 et Python 2.6+ :

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

Ceci est indépendant de la plateforme. Il termine également la ligne finale par un caractère de nouvelle ligne, ce qui est une meilleure pratique UNIX .

A partir de Python 3.6, "{}\n".format(item)peut être remplacé par un f-chaîne: f"{item}\n".

orluke
la source
je ne veux pas ajouter "\ n" pour le dernier élément, que faire? ne veux pas si la condition
pyd
4
@pyd Remplace la boucle for parfile_handler.write("\n".join(str(item) for item in the_list))
orluke
88

Encore une autre façon. Sérialiser en json en utilisant simplejson (inclus en tant que json dans python 2.6):

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

Si vous examinez output.txt:

[1, 2, 3, 4]

Ceci est utile car la syntaxe est pythonique, elle est lisible par l'homme et peut être lue par d'autres programmes dans d'autres langues.

Jason Baker
la source
39

J'ai pensé qu'il serait intéressant d'explorer les avantages de l'utilisation d'un genexp, alors voici mon avis.

L'exemple de la question utilise des crochets pour créer une liste temporaire et est donc équivalent à:

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

Qui construit inutilement une liste temporaire de toutes les lignes qui seront écrites, cela peut consommer des quantités importantes de mémoire en fonction de la taille de votre liste et du niveau de verbosité de la sortie de str(item).

Supprimer les crochets (équivalent à la suppression de l' list()appel d' habillage ci-dessus) passera à la place un générateur temporaire à file.writelines():

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

Ce générateur créera itemà la demande une représentation terminée par une nouvelle ligne de vos objets (c'est-à-dire au fur et à mesure de leur écriture). C'est bien pour deux raisons:

  • Les surcharges de mémoire sont petites, même pour les très grandes listes
  • S'il str(item)est lent, le fichier progresse à mesure que chaque élément est traité

Cela évite les problèmes de mémoire, tels que:

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

(J'ai déclenché cette erreur en limitant la mémoire virtuelle maximale de Python à ~ 100 Mo avec ulimit -v 102400).

En mettant de côté l'utilisation de la mémoire, cette méthode n'est en fait pas plus rapide que l'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 sous Linux)

RobM
la source
20

Parce que je suis paresseux ....

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
la source
les listes json sont-elles sérialisables?
kRazzy R
1
Oui en effet, ils le sont!
CommandoScorch
1
import json; test_list = [1,2,3]; list_as_a_string = json.dumps (test_list); #list_as_a_string est maintenant la chaîne '[1,2,3]'
CommandoScorch
Je fais ça with open ('Sp1.txt', 'a') as outfile: json.dump (sp1_segments, outfile) logger.info ("Saved sp_1 segments"); le problème est que mon programme s'exécute trois fois, et les résultats de trois exécutions sont en train d'être écrasés. existe-t-il un moyen d'ajouter 1-2 lignes vides pour que les résultats de chaque analyse soient discernables?
kRazzy R
1
Absolument! pourriez-vous faire à la place json.dump(sp1_segments + "\n\n", outfile)?
CommandoScorch
19

Sérialiser la liste dans un fichier texte avec une valeur séparée par des virgules

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

En général

Voici la syntaxe de la méthode writelines ()

fileObject.writelines( sequence )

Exemple

#!/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()

Référence

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

Marvin W
la source
13
file.write('\n'.join(list))
mtasic85
la source
1
Il convient de noter que cela nécessitera que le fichier soit ouvert en tant que texte pour être vraiment neutre sur la plate-forme.
Jason Baker,
2
Comment obtenez-vous la filevariable?
Jonathan Morales Vélez
8
with open ("test.txt","w")as fp:
   for line in list12:
       fp.write(line+"\n")
Shankar
la source
7

Vous pouvez également utiliser la fonction d'impression si vous êtes sur python3 comme suit.

f = open("myfile.txt","wb")
print(mylist, file=f)
Nandita Damaraju
la source
n'est-ce pas mettre une seule ligne dans monfichier.txt, quelque chose comme: ['a', 'b', 'c'] au lieu d'écrire chacun a, b, c sur chaque ligne.
Harry Duong
3

Pourquoi n'essayez-vous pas

file.write(str(list))
Bob
la source
2

Cette logique convertira d'abord les éléments de la liste en string(str). Parfois, la liste contient un tuple comme

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

Cette logique écrira pour classer chaque tuple dans une nouvelle ligne. Nous pouvons utiliser plus tard evallors du chargement de chaque tuple lors de la lecture du fichier:

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
la source
1

Une autre façon d'itérer et d'ajouter une nouvelle ligne:

for item in items:
    filewriter.write(f"{item}" + "\n")
Alex
la source
1

En python> 3, vous pouvez utiliser printet *pour le déballage des arguments:

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

Soit avg la liste, puis:

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

Vous pouvez utiliser %eou %sselon vos besoins.

Belthazar
la source
-2

En Python3, vous pouvez utiliser cette boucle

with open('your_file.txt', 'w') as f:
    for item in list:
        f.print("", item)
Nikhil B
la source
-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

Comment ça marche: Tout d'abord, ouvrez un fichier en utilisant la fonction open intégrée et en spécifiant le nom du fichier et le mode dans lequel nous voulons ouvrir le fichier. Le mode peut être un mode de lecture («r»), un mode d'écriture («w») ou un mode d'ajout («a»). Nous pouvons également spécifier si nous lisons, écrivons ou ajoutons en mode texte ('t') ou en mode binaire ('b'). Il y a en fait beaucoup plus de modes disponibles et l'aide (ouverte) vous donnera plus de détails à leur sujet. Par défaut, open () considère le fichier comme un fichier «t'ext et l'ouvre en mode« r ». Dans notre exemple, nous ouvrons d'abord le fichier en mode texte d'écriture et utilisons la méthode d'écriture de l'objet de fichier pour écrire dans le fichier, puis nous fermons finalement le fichier.

L'exemple ci-dessus est tiré du livre "A Byte of Python" de Swaroop C H. swaroopch.com

vayah
la source
5
Cela écrit une chaîne dans un fichier, pas une liste (de chaînes) comme l'OP le demande
gwideman