2012-02-13 21 views
13

Voglio scrivere su un file usando un metodo non bloccante in Python. Su alcuni googlilingua, ho trovato che la lingua supporta lo fcntl per farlo, ma il metodo per implementare lo stesso non mi è molto chiaro.Come scrivere su un file usando IO non bloccanti?

Questo è il frammento di codice (non so dove sto andando male):

import os, fcntl 
nf = fcntl.fcntl(0,fcntl.F_UNCLK) 
fcntl.fcntl(0,fcntl.F_SETFL , nf | os.O_NONBLOCK) 
nf = open ("test.txt", 'a') 
nf.write (" sample text \n") 

E 'questo il modo corretto per eseguire un'operazione non-blocking IO su un file? Ne dubito. Inoltre, potresti suggerire altri moduli in Python che mi consentono di farlo?

+0

possibile duplicato (http://stackoverflow.com/questions/319132/asynchronous-file-writing-possible-in-python) – jcollado

+0

[file di Asynchronous scrittura possibile in Python?] No, no, ho bisogno di mantenerlo semplice usando solo fcntl :) – Rahul

risposta

14

Questo è come si accende la modalità non-blocking su di un file in UNIX:

fd = os.open("filename", os.O_CREAT | os.O_WRONLY | os.O_NONBLOCK) 
os.write(fd, "data") 
os.close(fd) 

Su UNIX, tuttavia, turning on non-blocking mode has no visible effect for regular files! Anche se il file è in modalità non bloccante, la chiamata os.write non verrà restituita immediatamente, ma verrà interrotta fino al completamento della scrittura. Per dimostrare a voi stessi sperimentalmente, provate questo:

import os 
import datetime 

data = "\n".join("testing\n" * 10 for x in xrange(10000000)) 
print("Size of data is %d bytes" % len(data)) 

print("open at %s" % str(datetime.datetime.now())) 
fd = os.open("filename", os.O_CREAT | os.O_WRONLY | os.O_NONBLOCK) 
print("write at %s" % str(datetime.datetime.now())) 
os.write(fd, data) 
print("close at %s" % str(datetime.datetime.now())) 
os.close(fd) 
print("end at %s" % str(datetime.datetime.now())) 

Si noterà che la chiamata os.write ci vuole qualche secondo. Anche se la chiamata è non bloccante (tecnicamente, non blocca, sta dormendo), la chiamata è non asincrona.


AFAIK, non c'è modo di scrivere in un file in modo asincrono su Linux o su Windows. Puoi simularlo, tuttavia, usando i thread. Twisted ha un metodo chiamato deferToThread per questo scopo. Ecco come lo si utilizza:

from twisted.internet import threads, reactor 

data = "\n".join("testing\n" * 10 for x in xrange(10000000)) 
print("Size of data is %d bytes" % len(data)) 

def blocking_write(): 
    print("Starting blocking_write") 
    f = open("testing", "w") 
    f.write(data) 
    f.close() 
    print("End of blocking_write") 

def test_callback(): 
    print("Running test_callback, just for kicks") 

d = threads.deferToThread(blocking_code) 
reactor.callWhenRunning(cc) 
reactor.run() 
+0

Come potrei accedere all'oggetto reattore dall'interno di un LineReciver o altro protocollo simile creato da una fabbrica di server? – Sean

+0

Una scrittura non bloccante può essere eseguita su un file normale con POSIX AIO o Windows IOCP. – strcat

4

Le scritture vengono memorizzate nella cache dal sistema operativo e scaricate su disco dopo alcuni secondi. Cioè, loro "non stanno bloccando" già. Non devi fare niente di speciale.

+0

E se il file è effettivamente montato su una condivisione di rete? Sicuramente, la chiamata verrebbe restituita solo dopo aver ricevuto i ringraziamenti? – Flimm

+1

Depends del file system remoto e semantica implementata, sincrona o asincrona. Ci sono esempi di entrambi, o anche cose come "sincronizza alla chiusura". – jcea

Problemi correlati