Comment écrire correctement la ligne dans un fichier?

1070

J'ai l'habitude de faire print >>f, "hi there"

Cependant, il semble que cela print >>devient obsolète. Quelle est la façon recommandée de faire la ligne ci-dessus?

Mise à jour : Concernant toutes ces réponses avec "\n"... est-ce universel ou spécifique à Unix? IE, dois-je faire "\r\n"sur Windows?

Yaroslav Bulatov
la source
11
"\ n" n'est pas spécifique à Unix. Lorsque le fichier est ouvert en mode texte (par défaut), il est traduit automatiquement en la fin de ligne correcte pour la plate-forme actuelle. Écrire "\ r \ n" produirait "\ r \ r \ n" ce qui est faux.
D Coetzee
Ajoutez simplement l'instruction print ord (os.linesep) pour voir le code ascii (10 sur la plupart des systèmes UNIX)
Stefan Gruenwald
Pourquoi pensez-vous qu'il est obsolète?
xxx ---

Réponses:

1154

Cela devrait être aussi simple que:

with open('somefile.txt', 'a') as the_file:
    the_file.write('Hello\n')

De la documentation:

Ne pas utiliser os.linesepcomme terminaison de ligne lors de l'écriture de fichiers ouverts en mode texte (par défaut); utilisez plutôt un seul \ n sur toutes les plateformes.

Quelques lectures utiles:

Johnsyweb
la source
37
Cet exemple est meilleur que l'exemple ouvert / fermé. L'utilisation withest un moyen plus sûr de se souvenir de fermer un fichier.
Eyal
18
Je n'ai pas besoin d'appeler the_file.close()?
Hussain
19
non vous ne le faites pas: stackoverflow.com/questions/3012488/…
Tal Jerome
@Johnsyweb Pourquoi dites-vous "os.linesep. Il y a beaucoup de bonnes choses dans os!", Alors que vous avez précédemment recommandé dans le post de ne pas l'utiliser? Je soupçonne une modification ici, et cela pourrait être la raison des votes négatifs.
Horse SMith
1
@ user3226167: C'est un point intéressant. Mais pourquoi voudriez-vous ouvrir un fichier binaire pour écrire du texte brut?
Johnsyweb
961

Vous devez utiliser la print()fonction disponible depuis Python 2.6+

from __future__ import print_function  # Only needed for Python 2
print("hi there", file=f)

Pour Python 3, vous n'avez pas besoin de import, car la print()fonction est la valeur par défaut.

L'alternative serait d'utiliser:

f = open('myfile', 'w')
f.write('hi there\n')  # python will convert \n to os.linesep
f.close()  # you can omit in most cases as the destructor will call it

Citant de la documentation Python concernant les nouvelles lignes:

En sortie, si nouvelle ligne est rien, les '\n'caractères écrits sont traduits dans le séparateur de ligne par défaut du système, os.linesep. Si la nouvelle ligne est '', aucune traduction n'a lieu. Si la nouvelle ligne est l'une des autres valeurs légales, tous les '\n'caractères écrits sont traduits dans la chaîne donnée.

Sorin
la source
35
-1 "Si vous voulez être sûr, ajoutez os.linesep à la chaîne au lieu de \n" nécessiterait newline = "" sinon vous obtiendriez \r\r\nsur Windows. Il n'y a aucune raison de vouloir utiliser os.linesep du tout.
John Machin,
7
@Sorin: Votre modification pour ajouter le mode d'écriture est bien sûr une amélioration. Cependant, vous restez étrangement intransigeant sur os.linesep. Voir ma réponse. Par ailleurs, la documentation que vous citez est pour 3.x, mais cette partie est également valide pour 2.x en mode texte: tous les caractères '\ n' écrits sont traduits dans le séparateur de ligne par défaut du système, os.linesep * . .. Windows: l'écriture de os.linesep est la même que celle \r\nqui contient \nce qui est traduit en os.linesep, ce qui fait \r\nque le résultat final est \r\r\n.
John Machin
7
@John vous aviez raison, j'ai corrigé le bug os.linesep. Merci.
Sorin
3
Pour l'ajout n'est-ce pas à la open('myfile','a')place open('myfile','w')?
NeDark
6
@BradRuderman Cela fait partie de la norme POSIX pour ce qui constitue une "ligne" dans un fichier texte, c'est-à-dire que chaque ligne d'un fichier texte doit se terminer par une nouvelle ligne, même la dernière ligne.
wheeler
116

Les documents python recommandent cette façon:

with open('file_to_write', 'w') as f:
    f.write('file contents\n')

C'est comme ça que je le fais d'habitude :)

Déclaration de docs.python.org :

Il est recommandé d'utiliser le mot clé «with» pour traiter les objets fichier. Cela a l'avantage que le fichier est correctement fermé une fois sa suite terminée, même si une exception est levée en cours de route. C'est aussi beaucoup plus court que d'écrire des blocs try-finally équivalents.

j7nn7k
la source
1
Je n'aime pas cette façon quand j'ai besoin d'imbriquer l' withintérieur d'une boucle. Cela me fait constamment ouvrir et fermer le fichier au fur et à mesure de ma boucle. Peut-être que je manque quelque chose ici, ou c'est vraiment un inconvénient dans ce scénario particulier?
Sibbs Gambling
38
Que diriez-vous de boucler dans le avec?
j7nn7k
@ j7nn7k pour la ligne en fd:
momstouch
86

Concernant os.linesep:

Voici une session d'interprète Python 2.7.1 exacte non modifiée sur Windows:

Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.linesep
'\r\n'
>>> f = open('myfile','w')
>>> f.write('hi there\n')
>>> f.write('hi there' + os.linesep) # same result as previous line ?????????
>>> f.close()
>>> open('myfile', 'rb').read()
'hi there\r\nhi there\r\r\n'
>>>

Sous Windows:

Comme prévu, os.linesep ne produit PAS le même résultat que '\n'. Il n'y a aucun moyen que cela puisse produire le même résultat. 'hi there' + os.linesepest équivalent à 'hi there\r\n', ce qui n'est PAS équivalent à 'hi there\n'.

C'est aussi simple que cela: utilisation \nqui sera traduite automatiquement en os.linesep. Et c'est aussi simple que cela depuis le premier portage de Python vers Windows.

Il est inutile d'utiliser os.linesep sur des systèmes non Windows et cela produit des résultats incorrects sous Windows.

N'UTILISEZ PAS os.linesep!

John Machin
la source
excellent exemple - curieux si vous êtes un utilisateur d'ipython? de belles fonctions pour les sessions de formatage
Alvin
Je ne sais pas exactement ce que vous essayez de nous dire ici. os.linesep renverra le caractère de terme de ligne (ou chaîne) tel que défini par le système d'exploitation. Windows utilise \ r \ n pour les fins de ligne par défaut. Cependant, un seul \ n est reconnu. L'utilisation de \ n va donner une SORTIE entièrement portable mais os.linesep n'est pas faux sur Windows.
Gusdor
5
@Gusdor: Le fait est que si vous utilisez explicitement os.linesepdans Windows en mode texte, le résultat \r\r\nest incorrect. "Windows utilise ..." n'a pas de sens. La bibliothèque d'exécution C (et donc Python) se traduit \nà \r\nla sortie en mode texte. D'autres logiciels peuvent se comporter différemment. Ce n'est PAS le cas que tous les logiciels fonctionnant sous Windows reconnaissent un seul \ncomme séparateur de ligne lors de la lecture en mode texte. Python le fait. L'éditeur de texte du Bloc-notes de Microsoft ne fonctionne pas.
John Machin
6
On peut dire que quelqu'un d'autre le lira, pas vous, avec un logiciel de souris mickey qui va écorcher le supplément \r...
John Machin
2
@Gusdor venez-vous en python à partir d'un langage différent, où l'utilisation de '\ n' entraîne la sortie de '\ n' sur la fenêtre, plutôt que de '\ r \ n' - donc il manque le '\ r' attendu par dumb éditeurs de texte? Comme le dit John, ce n'est pas ainsi que se comporte Python - '\ n' est automatiquement remplacé par '\ r \ n', si c'est ce que os.linesep dit de faire. Par conséquent, dire explicitement os.linesep est «faux» ici. C'est comme Department of Redundancy Department. Oui, vous pouvez le faire. Non, tu ne veux pas.
ToolmakerSteve
55

Je ne pense pas qu'il existe une méthode "correcte".

J'utiliserais:

with open ('myfile', 'a') as f: f.write ('hi there\n')

In memoriam Tim Toady .

Hyperboreus
la source
Mais l'OP pourrait vouloir écrire des éléments supplémentaires dans le fichier. Ici, le fichier sera fermé lorsque le withhors de portée.
Keith
Cela pourrait vouloir être open(..., 'a')ou même 'at'.
mtrw
5
Euh, ouais. C'est l'idée d'utiliser avec. Si vous voulez garder le fichier ouvert, appelez simplement open au début et appelez close lorsque vous avez terminé ...
Hyperboreus
1
@mtrw. Vrai. OP était en annexe.
Hyperboreus
1
En ce qui concerne python, c'est RIP Tim Toady - et très très très légitimement
Mr_and_Mrs_D
21

En Python 3, c'est une fonction, mais en Python 2, vous pouvez l'ajouter en haut du fichier source:

from __future__ import print_function

Alors tu fais

print("hi there", file=f)
Keith
la source
17

Si vous écrivez beaucoup de données et que la vitesse est un problème, vous devriez probablement y aller f.write(...). J'ai fait une comparaison de vitesse rapide et c'était beaucoup plus rapide que print(..., file=f)lors de l'exécution d'un grand nombre d'écritures.

import time    

start = start = time.time()
with open("test.txt", 'w') as f:
    for i in range(10000000):
        # print('This is a speed test', file=f)
        # f.write('This is a speed test\n')
end = time.time()
print(end - start)

En moyenne, writej'ai terminé en 2,45 secondes sur ma machine, alors qu'il a printfallu environ 4 fois plus de temps (9,76 secondes). Cela étant dit, dans la plupart des scénarios du monde réel, ce ne sera pas un problème.

Si vous choisissez d'y aller, print(..., file=f)vous constaterez probablement que vous voudrez supprimer la nouvelle ligne de temps en temps, ou la remplacer par autre chose. Cela peut être fait en définissant le endparamètre facultatif , par exemple;

with open("test", 'w') as f:
    print('Foo1,', file=f, end='')
    print('Foo2,', file=f, end='')
    print('Foo3', file=f)

Quelle que soit la manière que vous choisissez, je suggère d'utiliser withcar cela rend le code beaucoup plus facile à lire.

Mise à jour : Cette différence de performances s'explique par le fait qu'elle writeest hautement tamponnée et retourne avant que les écritures sur le disque n'aient réellement lieu (voir cette réponse ), alors que print(probablement) utilise la mise en mémoire tampon des lignes. Un test simple pour cela serait de vérifier les performances pour les écritures longues également, où les inconvénients (en termes de vitesse) pour la mise en mémoire tampon de ligne seraient moins prononcés.

start = start = time.time()
long_line = 'This is a speed test' * 100
with open("test.txt", 'w') as f:
    for i in range(1000000):
        # print(long_line, file=f)
        # f.write(long_line + '\n')
end = time.time()

print(end - start, "s")

La différence de performances devient maintenant beaucoup moins prononcée, avec un temps moyen de 2,20 s pour writeet 3,10 s pour print. Si vous avez besoin de concaténer un tas de chaînes pour obtenir cette longue ligne, les performances en souffriront, donc les cas d'utilisation printqui seraient plus efficaces sont un peu rares.

Robin Keskisarkka
la source
10

Depuis la version 3.5, vous pouvez également utiliser le pathlibpour cela:

Path.write_text(data, encoding=None, errors=None)

Ouvrez le fichier pointé en mode texte, écrivez-y des données et fermez le fichier:

import pathlib

pathlib.Path('textfile.txt').write_text('content')
Johnson
la source
5

Lorsque vous avez dit Line, cela signifie certains caractères sérialisés qui se terminent par des caractères «\ n». La ligne doit être la dernière à un moment donné, nous devons donc considérer «\ n» à la fin de chaque ligne. Voici la solution:

with open('YOURFILE.txt', 'a') as the_file:
    the_file.write("Hello")

en mode ajout après chaque écriture, le curseur se déplace vers une nouvelle ligne, si vous souhaitez utiliser le wmode, vous devez ajouter des \ncaractères à la fin de la write()fonction:

the_file.write("Hello\n")
Reza Tanzifi
la source
1
"en mode ajout après chaque écriture, le curseur se déplace vers une nouvelle ligne" - non, ce n'est pas le cas.
Un Se
3

On peut également utiliser le iomodule comme dans:

import io
my_string = "hi there"

with io.open("output_file.txt", mode='w', encoding='utf-8') as f:
    f.write(my_string)
kmario23
la source
1

Pour écrire du texte dans un fichier dans le flacon peut être utilisé:

filehandle = open("text.txt", "w")
filebuffer = ["hi","welcome","yes yes welcome"]
filehandle.writelines(filebuffer)
filehandle.close()
Sashini Hettiarachchi
la source
0

Vous pouvez aussi essayer filewriter

pip install filewriter

from filewriter import Writer

Writer(filename='my_file', ext='txt') << ["row 1 hi there", "row 2"]

Écrit dans my_file.txt

Prend un itérable ou un objet avec __str__support.

Emin Bugra Saral
la source
0

Quand j'ai beaucoup besoin d'écrire de nouvelles lignes, je définis une lambda qui utilise une printfonction:

out = open(file_name, 'w')
fwl = lambda *x, **y: print(*x, **y, file=out) # FileWriteLine
fwl('Hi')

Cette approche présente l'avantage de pouvoir utiliser toutes les fonctionnalités disponibles avec la printfonction.

Mise à jour: Comme mentionné par Georgy dans la section des commentaires, il est possible d'améliorer encore cette idée avec la partialfonction:

from functools import partial
fwl = partial(print, file=out)

À mon humble avis, il s'agit d'une approche plus fonctionnelle et moins cryptique.

MxNx
la source
2
Ou un autre (probablement plus propre) façon d'écrire ceci: from functools import partial; fwl = partial(print, file=out).
Georgy
@Georgy Votre approche est si bonne qu'elle peut être donnée comme une nouvelle réponse.
MxNx
1
L'idée est la même que la vôtre, juste l'implémentation est un peu différente. Si vous le souhaitez, vous pouvez l'ajouter dans une modification à votre réponse. Ça me va.
Georgy