2009-11-12 24 views
27

Estoy tratando de averiguar si hay un patrón de facto para el acceso al archivo usando twisted. Muchos de los ejemplos que he visto (twisted.python.log, twisted.persisted.dirdbm, twisted.web.static) en realidad no parecen preocuparme por bloquear el acceso a los archivos.Acceso a archivos sin bloqueo con Twisted

Parece que debería haber una interfaz obvia, probablemente heredando de abstract.FileDescriptor, que todo el acceso a archivos debería atravesarlo como productor/consumidor.

¿He perdido algo o es solo que el uso principal para la programación asíncrona es para redes y realmente no ha sido resuelto para otras operaciones de descriptores de archivos, sin preocuparse por la pureza de IO no bloqueante?

+2

Creo que esta pregunta es un duplicado de http://stackoverflow.com/questions/1682515/how-non-blocking-read-write-throught-remote-filesystem –

+0

La pregunta se expresa mejor aquí. – Chris

Respuesta

-8

No estoy seguro de lo que quiere lograr. Cuando inicie sesión, Python se asegurará (mediante el registro global del intérprete) de que los mensajes de registro de varios hilos entren en el archivo uno después del otro.

Si le preocupa bloquear IO, el sistema operativo agrega los búfers predeterminados para sus archivos (generalmente 4KB) y puede pasar un tamaño de búfer en la llamada open().

Si le preocupa algo más, aclare su pregunta.

+8

¿Qué no está claro? Él quiere saber cómo leer/escribir archivos sin bloquear en Twisted. – truppo

14

Creo que está buscando fdesc module. Para obtener más información sobre E/S sin bloqueo en Python, también puede ver este video.

+0

@Flimm Se arregló. –

3

Hay un boleto abierto para esto en Twisted - #3983.

2

Después de mucha búsqueda, prueba y error, finalmente pensé cómo usar 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)) 

[Editar: Yo también acabo de descubrir una manera más sencilla que no requiere el uso de un protocolo]

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) 

Ejecutar ya sea de este modo:

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

En el segundo ejemplo, ¿Importa si el archivo está cerrado mientras que el diferido no se ha disparado? – Chris

+0

Buen punto @Chris. Quizás sería mejor renunciar al administrador de contexto y cerrar explícitamente el archivo en la devolución de llamada. – reubano

+0

Esto no bloquea el acceso al archivo. Los sistemas Unix ignoran silenciosamente 'setNonBlocking' cuando el fd apunta a un archivo ordinario del sistema de archivos. –

1

El FDESC El módulo puede ser útil para hablar asincrónicamente con un socket o pipe, pero cuando se le da un fd que se refiere a un archivo ordinario del sistema de archivos, bloquea a io (y a través de una interfaz bastante extraña). Para disco io, fdesc es efectivamente aceite de serpiente; no lo uses

A partir de mayo de 2017, la única forma razonable de obtener async disk io en twisted es envolviendo io llamadas sio en un deferToThread.