2009-11-12 2 views
27

Ich versuche herauszufinden, ob es ein defacto Muster für den Dateizugriff mit Twisted gibt. Viele Beispiele, die ich mir angeschaut habe (twisted.python.log, twisted.persisted.dirdbm, twisted.web.static), scheinen sich eigentlich nicht um das Blockieren des Dateizugriffs zu kümmern.Non-blocking Dateizugriff mit Twisted

Es scheint so, als müsste es eine offensichtliche Schnittstelle geben, die vermutlich von abstract.FileDescriptor stammt, dass alle Dateizugriffe als Producer/Consumer durchlaufen werden sollten.

Habe ich etwas verpasst oder ist es nur, dass die primäre Verwendung für Twisted in der asynchronen Programmierung ist für die Vernetzung und es wurde nicht wirklich für andere Dateideskriptor-Operationen ausgearbeitet, keine Sorgen über die Reinheit der nicht blockierenden IO?

+2

Ich denke, diese Frage ist ein Duplikat von http://stackoverflow.com/questions/1682515/how-non-blocking-read-write-thugrought-remote-filesystem –

+0

Die Frage ist hier besser gesagt. – Chris

Antwort

-8

Ich bin mir nicht sicher, was Sie erreichen möchten. Wenn Sie loggen, wird Python (durch das globale Interpreterprotokoll) sicherstellen, dass Protokollnachrichten von mehreren Threads nacheinander in die Datei gelangen.

Wenn Sie Bedenken haben, IO zu blockieren, fügt das Betriebssystem Standardpuffer für Ihre Dateien hinzu (normalerweise 4 KB), und Sie können eine Puffergröße im open()-Aufruf übergeben.

Wenn Sie über etwas anderes besorgt sind, dann bitte klären Sie Ihre Frage.

+8

Was ist nicht klar? Er möchte wissen, wie man Dateien liest/schreibt, ohne in Twisted zu blockieren. – truppo

14

Ich denke, Sie suchen nach der fdesc module. Weitere Informationen zu nicht blockierenden E/A in Python finden Sie unter video.

+0

@Flimm Es wurde behoben. –

3

Es gibt ein offenes Ticket dafür in Twisted - #3983.

2

Nach viel Suche, Versuch und Fehler, habe ich schließlich gedacht, wie man fdesc verwendet.

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: auch herausgefunden ich nur eine einfachere Art und Weise, die nicht die Verwendung eines Protokolls erfordert]

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) 

Run entweder wie so:

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

Im zweiten Beispiel spielt es eine Rolle, ob die Datei geschlossen ist, während der Deferred nicht ausgelöst wurde? – Chris

+0

Guter Punkt @ Chris. Vielleicht wäre es besser, auf den Kontextmanager zu verzichten und die Datei im Callback explizit zu schließen. – reubano

+0

Dies blockiert jedoch den Dateizugriff. Unix-Systeme ignorieren "setNonBlocking" stillschweigend, wenn das fd auf eine gewöhnliche Dateisystemdatei zeigt. –

1

Die FDESC Modul kann nützlich sein, um asynchron mit einem Socket oder einer Pipe zu sprechen, aber wenn es eine fd erhält, die auf eine gewöhnliche Dateisystemdatei verweist, blockiert es io (und über eine ziemlich seltsame Schnittstelle bei diesem). Für Disk-io ist fdesc effektiv Schlangenöl; benutze es nicht.

Ab Mai 2017 ist der einzige vernünftige Weg, um Async-Disk io in twisted zu bekommen, indem synchrone io Anrufe in einem deferToThread Wrapping.