Подтвердить что ты не робот

Неблокирующий доступ к файлам с помощью Twisted

Я пытаюсь выяснить, существует ли шаблон defacto для доступа к файлам с использованием скрученного. Множество примеров, на которые я смотрел (twisted.python.log, twisted.persisted.dirdbm, twisted.web.static), по-видимому, не беспокоит блокировку доступа к файлам.

Похоже, что должен быть какой-то очевидный интерфейс, возможно, наследуемый от abstract.FileDescriptor, чтобы весь доступ к файлам проходил через него как производитель/потребитель.

Я что-то пропустил или это просто то, что основное использование для скрутки в асинхронном программировании - для сетей, и на самом деле оно не было разработано для других операций дескриптора файла, не беспокоясь о чистоте неблокирующего IO?

4b9b3361

Ответ 1

Я думаю, вы ищете fdesc module. Для получения дополнительной информации о неблокирующем вводе-выводе в Python вы также можете посмотреть этот video.

Ответ 2

Существует открытый билет для этого в Twisted - # 3983.

Ответ 3

После большого количества поиска, проб и ошибок, я наконец понял, как использовать 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: Я также просто выяснил более простой способ, который не требует использования протокола]

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)

Выполнить так:

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

Ответ 4

Модуль fdesc может быть полезен для асинхронного общения с сокетом или каналом, но при задании fd, который относится к обычному файлу файловой системы, он блокирует io (и через довольно нечетный интерфейс). Для диска io fdesc является эффективным змеевым маслом; не используйте его.

По состоянию на май 2017 года единственный разумный способ получить асинхронный диск io в twisted - это обернуть синхронные вызовы io в deferToThread.

Ответ 5

Я не уверен, чего вы хотите достичь. Когда вы выполняете ведение журнала, Python будет проверять (по протоколу глобального интерпретатора), что сообщения журнала из нескольких потоков вступают в файл один за другим.

Если вы обеспокоены блокировкой ввода-вывода, то ОС добавляет буферы по умолчанию для ваших файлов (обычно 4 КБ), и вы можете передать размер буфера в вызове open().

Если вы обеспокоены чем-то другим, пожалуйста, уточните свой вопрос.