2012-03-22 10 views
15

Sto eseguendo un test e ho scoperto che il file non viene effettivamente scritto finché non controllo C per interrompere il programma. Qualcuno può spiegare perché ciò potrebbe accadere?Come mai un file non viene scritto finché non interrompo il programma?

Mi aspettavo che scrivesse allo stesso tempo, così ho potuto leggere il file nel mezzo del processo.

import os 
from time import sleep 

f = open("log.txt", "a+") 
i = 0 
while True: 
    f.write(str(i)) 
    f.write("\n") 
    i += 1 
    sleep(0.1) 
+0

Re: "spiegare perché", vedi http://stackoverflow.com/questions/ 1450551/buffered-io-vs-unbuffered-io –

risposta

49

La scrittura su disco è lenta, quindi molti programmi memorizzano le scritture in blocchi di grandi dimensioni che scrivono tutto in una volta. Questo è chiamato buffering, e Python lo fa automaticamente quando si apre un file.

Quando si scrive sul file, si sta effettivamente scrivendo su un "buffer" in memoria. Quando si riempie, Python lo scriverà automaticamente sul disco. Si può dire che "scrivere tutto nel buffer su disco adesso" con

f.flush() 

Questo non è del tutto l'intera storia, perché il sistema operativo sarà probabilmente tampone scrive pure. Si può dire che di scrivere il buffer del file con

os.fsync(f.fileno()) 

Infine, si può dire Python non per tamponare un file particolare con open(f, "w", 0) o soltanto di mantenere un buffer di 1-linea con open(f,"w", 1). Naturalmente, questo rallenterà tutte le operazioni su quel file, perché le scritture sono lente.

+0

+1 veramente informativo – twneale

+4

Si noti che 'ss()' gratuiti sono la rovina delle persone con laptop con unità di dischi rotanti che si preoccupano della loro durata della batteria. Non è necessario chiamare 'fsync()' per rendere il contenuto visibile ad altri programmi; è più vicino alla visibilità dopo un riavvio imprevisto (anche se non è necessariamente una condizione sufficiente neanche lì). –

+0

@CharlesDuffy: 'Non è necessario chiamare fsync() per rendere visibile il contenuto ad altri programmi': perché? Penso che se il tuo programma non è finito e altri programmi leggono il file, il suo contenuto potrebbe non essere aggiornato. –

5

È necessario f.close() per svuotare il file scrivere tampone fuori al file. O nel tuo caso potresti semplicemente voler fare un f.flush(); os.fsync(); in modo da poter continuare il ciclo con l'handle di file aperto.

Non dimenticare di import os.

+0

... o 'f.flush()' –

+1

In effetti, ma questo non garantisce un writeout completo su disco senza un os.fsync() – deed02392

+1

Non tutto il modo per disco , ma se è visibile ad altri programmi, è quello che sta chiedendo qui. os.fsync() è costoso, e non dovrebbe essere usato a meno che tu non sappia _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | Si noti che anche la maggior parte dei database ha un modo per disabilitare fsync - a volte l'utente * vuole * rischiare la corruzione dei dati per rendere le cose veloci. –

1

Si vuole controllare file.flush() - anche se di prendere atto che questo potrebbe non scrivere i dati su disco, per citare:

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

La chiusura del file (file.close()) garantirà inoltre che i dati vengono scritti - usando with farà questo modo implicito, ed è generalmente una scelta migliore per maggiore leggibilità e la chiarezza - per non parlare di risolvere altri problemi potenziali.

0

Questo è un windows-ism. Se aggiungi un esplicito .close() quando hai finito con il file, apparirà in explorer in quel momento. Anche solo il flushing potrebbe essere sufficiente (non ho una finestra di windows a portata di mano per testare). Fondamentalmente, f.write in realtà non scrive, si aggiunge al buffer di scrittura - finché il buffer non viene scaricato non lo vedrai.

In questo caso, in questa situazione i file verranno visualizzati come file a 0 byte.

0

File Handler da scaricare.

f.flush() 
0

Il file non viene scritto, come il buffer di uscita non è sempre lavata fino alla raccolta dei rifiuti ha effetto, e svuota il buffer di I/O (più che probabile chiamando f.close()).

In alternativa, nel proprio ciclo, è possibile chiamare f.flush() seguito da os.fsync(), come documentato here.

f.flush() 
os.fsync() 

Detto questo, se mai intenzione di condividere i dati in quel file con altre parti del codice, mi raccomando utilizzando un oggetto StringIO.

1

si deve forzare la scrittura, così ho io uso le seguenti linee per assicurarsi che un file viene scritto:

# Two commands together force the OS to store the file buffer to disc 
    f.flush() 
    os.fsync(f.fileno()) 
Problemi correlati