Использование select/poll/kqueue/kevent для просмотра каталога на наличие новых файлов

StackOverflow https://stackoverflow.com/questions/1165571

Вопрос

В моем приложении мне нужно просмотреть каталог на наличие новых файлов.Объем трафика очень велик, и будет появляться минимум сотни новых файлов в секунду.В настоящее время я использую цикл занятости с такой идеей:

while True:
  time.sleep(0.2)
  if len(os.listdir('.')) > 0:
    # do stuff

После запуска профилирования я вижу много времени, проведенного в режиме сна, и мне интересно, должен ли я изменить это, чтобы вместо этого использовать опрос.

Я пытаюсь использовать один из доступных классов в select чтобы опросить мой каталог, но я не уверен, действительно ли это работает, или я просто делаю это неправильно.

Я получаю fd для своего каталога с:

fd = os.open('.', os.O_DIRECT)

Затем я попробовал несколько методов, чтобы увидеть, когда изменяется каталог.В качестве примера, одна из вещей, которые я попробовал, была:

poll = select.poll()
poll.register(fd, select.POLLIN)

poll.poll()  # returns (fd, 1) meaning 'ready to read'

os.read(fd, 4096) # prints largely gibberish but i can see that i'm pulling the files/folders contained in the directory at least

poll.poll()  # returns (fd, 1) again

os.read(fd, 4096) # empty string - no more data

Почему poll() действует так, как будто есть больше информации для чтения?Я предположил, что это было бы сделано только в том случае, если бы что-то изменилось в каталоге.

Возможно ли вообще то, что я пытаюсь здесь сделать?

Если нет, есть ли какая-либо другая лучшая альтернатива while True: look for changes ?

Это было полезно?

Решение

После запуска профилирования я вижу много времени, проведенного в режиме сна, и мне интересно, должен ли я изменить это, чтобы вместо этого использовать опрос.

Похоже, ты уже делай синхронный опрос, путем проверки состояния через регулярные промежутки времени.Не беспокойтесь о времени, "проведенном" в sleep, это не будет потреблять процессорное время.Он просто передает управление операционной системе, которая запускает процесс по истечении запрошенного тайм-аута.

Вы могли бы рассмотреть возможность асинхронного цикла событий с использованием библиотеки, которая прослушивает уведомления об изменениях файловой системы, предоставляемые операционной системой, но сначала подумайте, дает ли это вам какие-либо реальные преимущества в данной конкретной ситуации.

Другие советы

FreeBSD и, следовательно, Mac OS X предоставляют аналог inotify под названием kqueue.Введите man 2 kqueue на компьютере с FreeBSD для получения дополнительной информации.Для kqueue во Freebsd у вас есть PyKQueue, доступный по адресу http://people .freebsd.org /~белый/PyKQueue/, к сожалению, активно не обслуживается, поэтому ваш пробег может варьироваться.

Почему бы не использовать оболочку Python для одной из библиотек для мониторинга изменений файлов, например геймин или inotify (найдите pyinotify, мне разрешено размещать только одну гиперссылку как новому пользователю ...) - это наверняка будет быстрее, а низкоуровневый материал уже выполнен на уровне C для вас, используя интерфейсы ядра...

Возможно, вы захотите взглянуть на выберите.kqueue - Я не использовал его, но kqueue, я полагаю, является подходящим интерфейсом для этого в BSD, поэтому вы можете отслеживать файлы / каталоги и перезванивать, когда и только когда они меняются

Я написал библиотеку и оболочку, которые должны справиться с этим за вас.

http://github.com/gorakhargosh/watchdog

Хотя kqueue - это очень тяжелый способ мониторинга каталогов Я был бы признателен, если бы вы могли протестировать и проверить любую производительность проблемы, с которыми вы можете столкнуться.Патчи также приветствуются.

ХТХ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top