Я использую twsited INotify для мониторинга каталога /dev для мониторинга добавления новых последовательных устройств. Используемый мной код аналогичен приведенному ниже.
notifier = INotify()
notifier.watch(FilePath("/dev"), IN_CREATE, callbacks=[self.created])
notifier.startReading()
def created(self, ignored, path, mask):
...
blocking code
...
Проблема, с которой я сталкиваюсь в данный момент, - это когда создается "созданная", она блокирует мой реактор, поэтому другие сетевые сеансы (у меня есть TCP и UDP-соединения, связанные с одним и тем же реактором) должны ждать "созданного" 'для завершения.
Кто-нибудь знает, как я могу заставить "созданный" метод работать в фоновом режиме, чтобы он не блокировал мой реактор?
Спасибо,
Саймон
Все обработчики событий в Twisted run в "потоке реакторов" - UDP, TCP и действительно inotify. Ожидается, что все они будут сотрудничать с системой, не блокируя ее. Итак, в этом смысле это просто вопрос о том, как писать хорошие обработчики событий в Twisted, а не о inotify в частности.
Существует множество вариантов предотвращения блокировки. Трудная вещь в ответе на ваш вопрос заключается в том, что правильный вариант зависит от того, почему именно текущий код блокируется.
Он делает сокеты ввода/вывода? Используйте Twisted non- блокировка API-интерфейс сокета ввода-вывода.
Это делает ввод/вывод файловой системы? Возможно, вам понадобится использовать поток, поскольку non- блокировка файловой системы ввода-вывода затруднена (возможно, не невозможна) без нее.
Говорит ли он с базой данных SQL? Возможно, twisted.enterprise.adbapi может помочь.
И так далее.
Я не знаю, покрывает ли это случай, в котором вы находитесь. Однако я остановлюсь на двух вещах. Во-первых, вполне естественно использовать потоки в программе Twisted. Большая часть Twisted существует, поэтому вам не придется использовать потоки, но если вы придете к тому обстоятельству, когда потоки выполняют свою работу, и ничего больше не делают - идите на это (с осторожностью;). У Twisted даже есть помощники, чтобы облегчить его, например, deferToThread
, упомянутый zeekay. Во-вторых, выберите подходящее решение для задачи. Сбор всех "блокирующих" проблем лишь немного меньше, чем сбор всех задач общего программирования. Существует множество возможных решений. Некоторые, например, потоки, похоже, имеют широкий диапазон применимости, но с небольшой осторожностью вы можете найти что-то более подходящее для конкретного обстоятельства.
Кроме того, посмотрите на Twisted: Заблокируйте блокировку non- для дальнейшего объяснения.
Вы можете использовать twisted.internet.threads.deferToThread
для запуска вашего блокирующего кода в потоке:
deferToThread(self.created, ignored, path mask)