785 votes

Écrire une liste dans un fichier avec Python

Est-ce la façon la plus propre d'écrire une liste dans un fichier, puisque 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...

43 votes

Notez bien que writelines n'ajoute pas de nouvelles lignes parce qu'il reflète le modèle readlines qui ne les supprime pas non plus.

0 votes

C'est entre json et pickle. lisez tout à ce sujet - stackoverflow.com/questions/27745500/

1089voto

Alex Martelli Points 330805

Vous pouvez utiliser une boucle :

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

En Python 2, vous pouvez également utiliser

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

Si vous tenez à un seul appel de fonction, supprimez au moins les crochets. [] de façon à ce que les chaînes à imprimer soient fabriquées une par une (un genexp plutôt qu'un listcomp) -- il n'y a aucune raison d'occuper toute la mémoire nécessaire pour matérialiser la liste entière des chaînes.

8 votes

Ce n'est pas très complexe, mais pourquoi ne pas utiliser pickle ou json pour ne pas avoir à se soucier de la sérialisation et de la désérialisation ?

103 votes

Par exemple, parce que vous voulez un fichier texte de sortie qui peut être facilement lu, modifié, etc., avec un élément par ligne. Ce n'est pas un désir rare;-).

1 votes

J'ai trouvé que le \n dans la première était redondant sur Python 2.7/Windows

438voto

IfLoop Points 59461

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

Si vous essayez simplement de sérialiser une liste sur le disque pour une utilisation ultérieure par la même application python, vous devriez décapage 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)

41 votes

+1 - Pourquoi réinventer la roue alors que Python intègre la sérialisation ?

20 votes

+1 - le fichier de sortie est quelque chose comme : open( "save.p", "wb" ) infile est quelque chose comme : open( "save.p", "rb" )

2 votes

Le problème est que la liste doit tenir dans la mémoire. Si ce n'est pas le cas, la stratégie ligne par ligne est en effet envisageable (ou alors une alternative comme dans stackoverflow.com/questions/7180212/ )

349voto

osantana Points 1005

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 de caractères en utilisant une expression de générateur :

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

Rappelez-vous que tous les itemlist doit être en mémoire, donc, faites attention à la consommation de mémoire.

26 votes

Pas de nouvelle ligne de queue, utilise 2x l'espace par rapport à la boucle.

8 votes

Bien sûr, la première question qui vient à l'esprit est de savoir si le PO a besoin ou non qu'il se termine par une nouvelle ligne et si la quantité d'espace a de l'importance. Vous savez ce qu'on dit des optimisations prématurées.

19 votes

Un inconvénient : Cette méthode construit tout le contenu du fichier en mémoire avant de l'écrire, de sorte que l'utilisation maximale de la mémoire peut être élevée.

93voto

Jason Baker Points 56682

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

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

Si vous examinez le fichier de sortie.txt :

[1, 2, 3, 4]

C'est utile parce que la syntaxe est pythonique, qu'elle est lisible par l'homme et qu'elle peut être lue par d'autres programmes dans d'autres langues.

0 votes

C'est beaucoup mieux pour les chaînes de caractères multilignes

39voto

RobM Points 2681

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

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 ) )

Ce qui construit inutilement une liste temporaire de toutes les lignes qui seront écrites, ce qui peut consommer des quantités significatives de mémoire en fonction de la taille de votre liste et du caractère verbeux de la sortie de la commande str(item) est.

Supprimez les crochets (ce qui équivaut à supprimer l'emballage). list() ci-dessus) transmettra à la place un générateur à file.writelines() :

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

Ce générateur créera une représentation terminée par une nouvelle ligne de votre message. item à la demande (c'est-à-dire au fur et à mesure qu'ils sont écrits). Ceci est intéressant pour plusieurs raisons :

  • Les frais de mémoire sont faibles, même pour les très grandes listes.
  • Si str(item) est lent, il y a une progression visible dans le fichier au fur et à 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 la commande ulimit -v 102400 ).

Si l'on met de côté l'utilisation de la mémoire, cette méthode n'est pas vraiment plus rapide que l'originale :

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)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X