2009-11-12 12 views
27

Sto cercando di capire se esiste un modello defacto per l'accesso ai file utilizzando twistato. Un sacco di esempi che ho visto (twisted.python.log, twisted.persisted.dirdbm, twisted.web.static) in realtà non sembrano preoccuparsi del blocco per l'accesso ai file.Accesso file non bloccante con Twisted

Sembra che ci dovrebbe essere un'interfaccia ovvia, probabilmente ereditando da abstract.FileDescriptor, che tutti gli accessi ai file dovrebbero passare attraverso di esso come produttore/consumatore.

Ho perso qualcosa o è solo che l'utilizzo primario per intrecciati in programmazione asincrona è per il networking e non ha davvero stato elaborato per altre operazioni descrittore di file, senza preoccuparsi della purezza della IO non-blocking?

+2

Penso che questa domanda sia un duplicato di http://stackoverflow.com/questions/1682515/how-non-blocking-read-write-throught-remote-filesystem –

+0

La domanda è indicata meglio qui. – Chris

risposta

-8

Non sono sicuro di cosa si vuole ottenere. Quando esegui il logging, Python si assicurerà (tramite il log dell'interprete globale) che i messaggi di log provenienti da più thread entrino nel file uno dopo l'altro.

Se si è preoccupati del blocco dell'IO, il sistema operativo aggiunge i buffer predefiniti per i file (in genere 4KB) e si può passare una dimensione del buffer nella chiamata open().

Se sei preoccupato per qualcos'altro, quindi ti preghiamo di chiarire la tua domanda.

+8

Cosa non è chiaro? Vuole sapere come leggere/scrivere file senza bloccare in Twisted. – truppo

14

Penso che stiate cercando lo fdesc module. Per ulteriori informazioni sull'I/O non bloccante in Python, è anche possibile guardare questo video.

+0

@Flimm Risolto il problema. –

3

C'è un biglietto aperto per questo in Twisted - #3983.

2

Dopo molte ricerche, tentativi ed errori, ho finalmente capito come utilizzare fdesc.

from __future__ import print_function 

from twisted.internet.task import react 
from twisted.internet import stdio, protocol 
from twisted.internet.defer import Deferred 
from twisted.internet.fdesc import readFromFD, setNonBlocking 


class FileReader(protocol.Protocol): 
    def __init__(self, filename): 
     self.f = open(filename, 'rb') 

    def dataReceived(self, data): 
     self.transport.write(data) 

    def connectionMade(self): 
     fd = self.f.fileno() 
     setNonBlocking(fd) 
     readFromFD(fd, self.dataReceived) 

    def connectionLost(self, reason): 
     self.f.close() 

def main(reactor, filename): 
    stdio.StandardIO(FileReader(filename)) 

[Edit: Ho anche appena trovato un modo più semplice che non richiede l'uso di un protocollo]

def getFile(filename): 
    with open(filename) as f: 
     d = Deferred() 
     fd = f.fileno() 
     setNonBlocking(fd) 
     readFromFD(fd, d.callback) 
     return d 


def main(reactor, filename): 
    d = getFile(filename) 
    return d.addCallback(print) 

funzionare sia in questo modo:

react(main, ['/path/to/file']) 
+1

Nel secondo esempio, è importante se il file viene chiuso mentre non è stato eseguito il rinvio? – Chris

+0

Buon punto @ Chris. Forse sarebbe meglio rinunciare al gestore del contesto e chiudere esplicitamente il file nel callback. – reubano

+0

Questo però blocca l'accesso ai file. I sistemi Unix ignorano silenziosamente 'setNonBlocking' quando il file fd punta a un normale file system. –

1

Il fdesc il modulo potrebbe essere utile per parlare in modo asincrono con un socket o una pipe, ma quando viene dato un fd che si riferisce ad un file di filesystem ordinario, blocca io (e tramite un'interfaccia piuttosto strana). Per il disco io, fdesc è effettivamente olio di serpente; non usarlo

A partire da maggio 2017, l'unico modo ragionevole per ottenere il disco asincrono in twisted consiste nel disporre le chiamate sincrone io in un deferToThread.