2013-09-24 19 views
31

ho capito che quando scrivo in un file utilizzando python che aspettare la fine del mio file Python per eseguirlo:Python 2.7: scrivere sul file istantaneamente

outputFile = open("./outputFile.txt","a") 
outputFile.write("First") 
print "Now you have 10sec to see that outputFile.txt is still the same as before" 
time.sleep(10) 
outputFile.write("Second") 
print "Now if you look at outputFile.txt you will see 'First' and 'Second'" 

Come sto suppongo di fare pitone scrivere immediatamente al file di output?

risposta

47

È possibile utilizzare flush() oppure impostare l'oggetto file su unbuffered.

Dettagli sull'utilizzo di tale parametro per open()here.

Così si avrebbe cambiare il vostro invito aperto a -

outputFile = open("./outputFile.txt", "a", 0) 
+2

Grazie, la seconda opzione è la migliore per me perché non desidero scrivere outputFile.flush() ogni volta, ma entrambe funzionano. – elbajo

+1

Invece di lasciare il file aperto durante operazioni a tempo intensivo, potrebbe valere la pena di prendere in considerazione l'istruzione with che realizzerebbe la stessa cosa. – nachshon

+1

@nachshon "realizza la stessa cosa": non per me sul mio sistema (RHEL 6.8 con [conda] (https://en.wikipedia.org/wiki/Conda_ (package_manager)) basato su Python 2.7.13). La chiamata 'os.fsync()' menzionata nella risposta [ffeast] (https://stackoverflow.com/a/41506739/257924) è richiesta (non posso dire con certezza per Python basato su Microsoft Windows o altri sistemi operativi). – bgoodr

14

Forza con la funzione flush(), aggiungere

outputFile.flush() 

alla fine del codice.

+2

Se questo codice viene aggiunto a Alla fine del file Python, non si ottiene nulla che non sarebbe stato comunque quando il file è stato chiuso. Invece dovrebbe essere eseguito possibilmente più volte - ogni volta che si desidera assicurarsi che tutto l'output prodotto finora sia scritto nel file. – martineau

3

Come @RyPeck detto è possibile utilizzare flush() o impostare l'oggetto file per essere unbuffered. Ma tenere presente quanto segue (da https://docs.python.org/2/library/stdtypes.html?highlight=file%20flush#file.flush):

svuotare il buffer interno, come fflush di stdio().

Nota flush() non scrive necessariamente i dati del file su disco. Usa flush() seguito da os.fsync() per assicurare questo comportamento.

E una citazione da man 3 fflush:

noti che fflush(), vampate solo i buffer user-space fornite dalla libreria C. Per garantire che i dati vengano archiviati fisicamente sul disco, anche i buffer del kernel devono essere svuotati, ad esempio, con sync (2) o fsync (2).

+0

Call os.fsync() interrompe il mio codice subito –

+0

@Nam 'os.fsync()' funziona perfettamente sul mio sistema (RHEL 6.8 con [conda] (https://en.wikipedia.org/wiki/Conda_ (package_manager)) - basato su Python 2.7.13). Sei sicuro di non avere problemi con il filesystem o un sistema sovraccarico? – bgoodr

+0

Non ne ho idea. Sono su Ubuntu Desktop 16 e Python 2.7 –

0

Proprio per unire tutte le risposte di cui sopra in un insieme di funzioni di utilità utile perché un requisito fondamentale della OP (e me!) È "because I don't want to write outputFile.flush() each time":

import os 
import tempfile 
import time 


def write_now(filep, msg): 
    """Write msg to the file given by filep, forcing the msg to be written to the filesystem immediately (now). 

    Without this, if you write to files, and then execute programs 
    that should read them, the files will not show up in the program 
    on disk. 
    """ 
    filep.write(msg) 
    filep.flush() 
    # The above call to flush is not enough to write it to disk *now*; 
    # according to https://stackoverflow.com/a/41506739/257924 we must 
    # also call fsync: 
    os.fsync(filep) 


def print_now(filep, msg): 
    """Call write_now with msg plus a newline.""" 
    write_now(filep, msg + '\n') 


# Example use with the with..as statement: 
with tempfile.NamedTemporaryFile(prefix='some_prefix_here.', suffix='.log', dir='.', delete=False) as logf: 
    print_now(logf, "this is a test1") 
    time.sleep(20) 
    print_now(logf, "this is a test2")