Modo corretto di scrivere la riga nel file?


1069

Sono abituato a fare print >>f, "hi there"

Tuttavia, sembra che print >>si sta deprecando. Qual è il modo consigliato per fare la riga sopra?

Aggiornamento : per quanto riguarda tutte quelle risposte con "\n"... è universale o specifico per Unix? IE, dovrei fare "\r\n"su Windows?


11
"\ n" non è specifico di Unix. Quando il file viene aperto in modalità testo (impostazione predefinita), viene tradotto automaticamente nella riga corretta che termina per la piattaforma corrente. Scrivere "\ r \ n" produrrebbe "\ r \ r \ n" che è sbagliato.
D Coetzee,

Basta aggiungere l'istruzione print ord (os.linesep) per vedere il codice ascii (10 sulla maggior parte dei sistemi UNIX)
Stefan Gruenwald

Perché pensi che sia deprecato?
xxx ---

Risposte:


1153

Questo dovrebbe essere semplice come:

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

Dalla documentazione:

Non utilizzare os.linesepcome terminatore di riga durante la scrittura di file aperti in modalità testo (impostazione predefinita); usa invece un singolo '\ n', su tutte le piattaforme.

Qualche lettura utile:


37
Questo esempio è migliore dell'esempio di apertura / chiusura. L'utilizzo withè un modo più sicuro di ricordare di chiudere un file.
Eyal,

18
Non devo chiamare the_file.close()?
Hussain,


@Johnsyweb Perché dici "os.linesep. Ci sono molte cose buone in os!", Quando in precedenza nel post hai raccomandato di non usarlo? Sto sospettando una modifica qui, e potrebbe essere la ragione dei voti negativi.
Cavallo SMith

1
@ user3226167: Questo è un punto interessante. Ma perché dovresti aprire un file binario per scrivere testo semplice?
Johnsyweb,

961

Dovresti usare la print()funzione disponibile da Python 2.6+

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

Per Python 3 non è necessario import, poiché print() funzione è quella predefinita.

L'alternativa sarebbe usare:

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

Citando dalla documentazione di Python per quanto riguarda le newline:

Sull'uscita, se newline è None, eventuali '\n'caratteri scritti vengono convertiti al separatore linea di default del sistema, os.linesep. Se newline è '', nessuna traduzione ha luogo. Se newline è uno degli altri valori legali, tutti i '\n'caratteri scritti vengono tradotti nella stringa specificata.


35
-1 "Se vuoi essere sicuro, aggiungi os.linesep alla stringa invece di \n" richiederebbe newline = "" altrimenti verrai \r\r\nsu Windows. Non c'è motivo di perdere tempo con os.linesep.
John Machin,

7
@Sorin: la tua modifica per aggiungere la modalità di scrittura è ovviamente un miglioramento. Tuttavia stranamente rimani intransigente su os.linesep. Vedi la mia risposta A proposito, la documentazione citata è per 3.x, ma questa parte è valida anche per 2.x in modalità testo: tutti i caratteri '\ n' scritti vengono tradotti nel separatore di riga predefinito di sistema, os.linesep * . .. Windows: scrivere os.linesep equivale a scrivere \r\nche contiene il \nquale viene tradotto in os.linesep e \r\nquindi il risultato finale è \r\r\n.
John Machin,

7
@Giovanni avevi ragione, ho corretto il bug os.linesep. Grazie.
sorin,

3
Per aggiungendo isnt esso open('myfile','a'), invece open('myfile','w')?
NeDark

6
@BradRuderman Fa parte dello standard POSIX per ciò che costituisce una "linea" in un file di testo, ovvero ogni riga in un file di testo deve essere terminata da una nuova riga, anche dall'ultima riga.
Wheeler

116

I documenti di Python raccomandano in questo modo:

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

Quindi questo è il modo in cui lo faccio di solito :)

Dichiarazione da docs.python.org :

È buona norma utilizzare la parola chiave "with" quando si ha a che fare con oggetti file. Ciò ha il vantaggio che il file viene chiuso correttamente al termine della sua suite, anche se viene sollevata un'eccezione. È anche molto più breve della scrittura di blocchi try-finally equivalenti.


1
Non mi piace in questo modo quando devo annidare l' withinterno di un ciclo. Questo mi fa aprire e chiudere costantemente il file mentre procedo nel mio ciclo. Forse mi manca qualcosa qui, o questo è davvero uno svantaggio in questo particolare scenario?
Sibbs Gioco d'azzardo

38
Che ne dici di fare un ciclo all'interno del con?
j7nn7k,

@ j7nn7k for line in fd:
momstouch

86

Per quanto riguarda os.linesep:

Ecco una sessione di interprete Python 2.7.1 inedita esatta su 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'
>>>

Su Windows:

Come previsto, os.linesep NON produce lo stesso risultato di '\n'. Non è possibile che produca lo stesso risultato. 'hi there' + os.linesepè equivalente a 'hi there\r\n', che NON è equivalente a 'hi there\n'.

È così semplice: uso \nche verrà tradotto automaticamente in os.linesep. Ed è stato così semplice sin dalla prima porta di Python su Windows.

Non ha senso utilizzare os.linesep su sistemi non Windows e produce risultati errati su Windows.

NON USARE os.linesep!


ottimo esempio: curioso se sei un utente ipython? belle funzioni per le sessioni di formattazione
Alvin,

Non sono del tutto sicuro di cosa stai cercando di dirci qui. os.linesep restituirà il carattere di riga (o stringa) come definito dal sistema operativo. Windows utilizza \ r \ n per terminazioni di linea per impostazione predefinita. Tuttavia, viene riconosciuto un singolo \ n. L'uso di \ n produrrà un OUTPUT completamente portatile ma os.linesep non è sbagliato su Windows.
Gusdor,

5
@Gusdor: Il punto è che se si utilizza esplicitamente os.linesepin Windows in modalità testo, il risultato è \r\r\nche è sbagliato. "Windows utilizza ..." non ha senso. La libreria runtime C (e quindi Python) translate \na \r\nsull'uscita in modalità testo. Altri software potrebbero comportarsi diversamente. NON è il caso che tutto il software in esecuzione su Windows riconosca un solitario \ncome separatore di riga durante la lettura in modalità testo. Python lo fa. L'editor di testo del Blocco note di Microsoft no.
John Machin,

6
Probabilmente qualcun altro lo leggerà, non tu, con un po 'di software di topolino che fallirà circa il \r...
John Machin,

2
@Gusdor stai arrivando a Python da una lingua diversa, dove l'uso di '\ n' produce l'output di '\ n' sulla finestra, piuttosto che '\ r \ n' - quindi manca il '\ r' previsto da muto editor di testo? Come dice John, non è così che si comporta Python: "\ n" viene automaticamente sostituito da "\ r \ n", se è quello che dice os.linesep. Quindi, dire esplicitamente os.linesep è "sbagliato" qui. È come Department of Redundancy Department. Si, puoi farlo. No, non vuoi.
ToolmakerSteve

55

Non penso che esista un modo "corretto".

Io userei:

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

In memoriam Tim Toady .


Ma l'OP potrebbe voler scrivere roba aggiuntiva nel file. Qui il file verrà chiuso quando non withrientra nell'ambito.
Keith,

Potrebbe voler essere open(..., 'a')o addirittura 'at'.
MTRW

5
Ehm, si. Questa è l'idea di usare con. Se vuoi mantenere il file aperto, chiama open all'inizio e chiama close quando hai finito ...
Hyperboreus,

1
@mtrw. Vero. OP stava aggiungendo.
Iperboro,

1
Per quanto riguarda il pitone è interessato è RIP Tim Toady - e molto molto molto giustamente
Mr_and_Mrs_D

21

In Python 3 è una funzione, ma in Python 2 puoi aggiungerlo all'inizio del file sorgente:

from __future__ import print_function

Allora lo fai

print("hi there", file=f)

17

Se stai scrivendo molti dati e la velocità è una preoccupazione che probabilmente dovresti seguire f.write(...). Ho fatto un confronto veloce della velocità ed è stato notevolmente più veloce rispetto a print(..., file=f)quando ho eseguito un gran numero di scritture.

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)

In media writeho finito in 2,45 secondi sulla mia macchina, mentreprint voluti circa 4 volte di più (9,76 secondi). Detto questo, nella maggior parte degli scenari del mondo reale questo non sarà un problema.

Se scegli di andare con print(..., file=f)te probabilmente scoprirai che vorresti sopprimere la nuova riga di volta in volta, o sostituirla con qualcos'altro. Questo può essere fatto impostando il endparametro opzionale , ad es.

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

Qualunque modo scegliate, suggerirei di utilizzarlo withpoiché rende il codice molto più facile da leggere.

Aggiornamento : questa differenza nelle prestazioni è spiegata dal fatto che writeè altamente bufferizzato e ritorna prima che avvenga qualsiasi scrittura su disco (vedi questa risposta ), mentre print(probabilmente) usa il buffering di linea. Un semplice test per questo sarebbe quello di verificare le prestazioni anche per le scritture lunghe, in cui gli svantaggi (in termini di velocità) per il buffering di linea sarebbero meno pronunciati.

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 differenza di prestazioni ora diventa molto meno pronunciata, con un tempo medio di 2,20 writesecondi e 3,10 secondi print. Se è necessario concatenare un sacco di stringhe per ottenere prestazioni così elevate, ne risentiranno le prestazioni, quindi i casi d'uso in cui printsarebbe più efficiente sono un po 'rari.


10

A partire da 3.5 puoi utilizzare anche pathliba tale scopo:

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

Apri il file a cui punta in modalità testo, scrivi i dati su di esso e chiudi il file:

import pathlib

pathlib.Path('textfile.txt').write_text('content')

5

Quando hai detto Linea significa alcuni caratteri serializzati che terminano con caratteri \ \ n. La linea dovrebbe essere l'ultima ad un certo punto, quindi dovremmo considerare '\ n' alla fine di ogni linea. Ecco la soluzione:

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

in modalità append dopo ogni scrittura il cursore si sposta su una nuova riga, se si desidera utilizzare la wmodalità è necessario aggiungere \ncaratteri alla fine della write()funzione:

the_file.write("Hello\n")

1
"in modalità append dopo ogni scrittura il cursore si sposta su una nuova riga" - no non lo è.
Un

3

Si può anche usare il iomodulo come in:

import io
my_string = "hi there"

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

1

Per scrivere il testo in un file nel pallone si può usare:

filehandle = open("text.txt", "w")
filebuffer = ["hi","welcome","yes yes welcome"]
filehandle.writelines(filebuffer)
filehandle.close()

0

Puoi anche provare filewriter

pip install filewriter

from filewriter import Writer

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

Scrive in my_file.txt

Accetta un iterabile o un oggetto con __str__supporto.


0

Quando ho bisogno di scrivere molte nuove righe, definisco una lambda che utilizza una printfunzione:

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

Questo approccio ha il vantaggio di poter utilizzare tutte le funzionalità disponibili con la printfunzione.

Aggiornamento: Come menzionato da Georgy nella sezione commenti, è possibile migliorare ulteriormente questa idea con la partialfunzione:

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

IMHO, questo è un approccio più funzionale e meno criptico.


2
O un altro (probabilmente più pulito) modo di scrivere questo: from functools import partial; fwl = partial(print, file=out).
Georgy,

@Georgy Il tuo approccio è così buono che può essere dato come una nuova risposta.
MxNx

1
L'idea è la stessa della tua, solo l'implementazione è un po 'diversa. Se lo desideri, puoi aggiungerlo in una modifica alla tua risposta. Mi sta bene.
Georgy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.