Создание нескольких наблюдателей с помощью сторожевого таймера Python

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

Теперь я хочу расширить свой сценарий, чтобы отслеживать 3 отдельных местоположения, но я просто не могу понять, как создать несколько наблюдателей для наблюдения за каждым из моих назначенных путей.

Я попытался что-то вроде следующего:

import time
import thread
import threading
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

event_handler = LoggingEventHandler()
observer = Observer()

paths = ["C:\dir1", "C:\dir2", "C:\dir3"]

for i in paths:
    targetPath = str(i)
    observer.schedule(event_handler, targetPath, recursive=True)
    observer.start_new_thread()

К сожалению, я получил сообщение об ошибке, указывающее, что у наблюдателя нет атрибута start_new_thread.

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

Должен ли я вместо этого создавать новый экземпляр класса наблюдателя для каждого пути? Или есть какой-то метод подачи одного экземпляра класса Observer по нескольким путям?

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

ДОПОЛНИТЕЛЬНЫЙ:

Благодаря @FogleBird я исправил проблему запуска потока, но я все еще застрял только с одним экземпляром, а не с тремя отдельными наблюдателями, наблюдающими за разными путями. Мой измененный код теперь выглядит так:

threads = []

for i in paths:
    targetPath = str(i)
    observer.schedule(event_handler, targetPath, recursive=True)
    threads.append(observer)

observer.start()
print threads

Это возвращает три объекта ObservedWatch, но все они имеют одинаковые данные:

[<Observer(Thread-1, started daemon 1548)>, <Observer(Thread-1, started daemon 1548)>, <Observer(Thread-1, started daemon 1548)>]

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

ДОПОЛНИТЕЛЬНО 2:

Я продолжал возиться с кодом, и теперь у меня есть кое-что, что кажется функциональным:

event_handler = LoggingEventHandler()
N2watch = Observer()
threads = []

for i in paths:
    targetPath = str(i)
    N2watch.schedule(event_handler, targetPath, recursive=True)
    threads.append(N2watch)

N2watch.start()

try:
    while True:
            time.sleep(1)
except KeyboardInterrupt:
    N2watch.stop()
N2watch.join()

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

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

Ваше здоровье.

ДОПОЛНИТЕЛЬНО 3:

Я отметил ответ FogleBird как лучший, потому что он был просто единственным и выявил проблемы с моим исходным кодом.

Мое предыдущее редактирование включало полностью рабочий код для мониторинга нескольких местоположений и, похоже, в настоящее время работает правильно.


person binarydogs    schedule 15.11.2013    source источник
comment
Вы нашли решение этой проблемы? Я пытаюсь реализовать то же самое.   -  person majidarif    schedule 22.07.2014
comment
Привет - да, последний раздел кода в сообщении выше оказался функциональным. У меня работало все, что ниже раздела с надписью ДОПОЛНИТЕЛЬНО 2.   -  person binarydogs    schedule 22.07.2014


Ответы (4)


В приведенном здесь примере кода показана функция с именем start, а не start_new_thread. Вы пробовали это?

https://pypi.python.org/pypi/watchdog

Кроме того, вам, вероятно, следует вызывать start только один раз после цикла for, а не внутри него.

person FogleBird    schedule 15.11.2013
comment
Спасибо @FogleBird. Я не знаю, где я взял codestart_new_threadcode, когда читал документацию. - person binarydogs; 15.11.2013

Отличный вопрос. Этот поток старше, но я нашел его, когда искал точную вещь, и я расширил вашу работу и добавил возможность передать файл со списком каталогов для просмотра. По умолчанию я не смотрю рекурсивно, я оставляю это кому-то другому для проверки. Надеюсь, это поможет любому, кто ищет ту же тему. Отличная работа!

Запустите, используя python watcher.py имя файла.

Где watcher.py — это то, что я назвал своим скриптом, а имя файла — это имя файла с моими путями.

Я перечисляю полные пути в файле, и они разделены символами новой строки.

i.e.:

C:\path1
C:\Path2\subpath1
C:\PATH3

watcher.py

import logging
import sys
import time
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler

# Attach a logging event AKA FileSystemEventHandler
event_handler = LoggingEventHandler()

# Create Observer to watch directories
observer = Observer()

# Take in list of paths. If none given, watch CWD
paths = open(sys.argv[1], 'r') if len(sys.argv) > 1 else '.'

# Empty list of observers
observers = []

# Base logging configuration
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S')

# Iterate through paths and attach observers
for line in paths:

    # Convert line into string and strip newline character
    targetPath = str(line).rstrip()

    # Schedules watching of a given path
    observer.schedule(event_handler, targetPath)

    # Add observable to list of observers
    observers.append(observer)

# Start observer
observer.start()

try:
    while True:

        # Poll every second
        time.sleep(1)

except KeyboardInterrupt:
    for o in observers:
        o.unschedule_all()

        # Stop observer if interrupted
        o.stop()

for o in observers:

    # Wait until the thread terminates before exit
    o.join()
person dwtorres    schedule 07.09.2016

Просто хочу добавить несколько замечаний:

Библиотека потоков и список потоков в коде могут немного сбивать с толку людей, которые только начинают использовать сторожевой таймер (включая меня). Они на самом деле не нужны в решении. Простой способ объяснить это просто:

  • создать одного наблюдателя
  • запланировать несколько «событий просмотра»
  • и запустите наблюдатель.

Вот и все.

person Jibin Liu    schedule 12.10.2016

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

import sys
import time
import logging
from watchdog.observers.polling import PollingObserver as Observer
from watchdog.events import LoggingEventHandler

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s - %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S')
    event_handler = LoggingEventHandler()
    observer = Observer()
    if len(sys.argv) > 1:
        for i in range(1, len(sys.argv)):
            observer.schedule(event_handler, sys.argv[i], recursive=True)
    else:
        observer.schedule(event_handler, '.', recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
person Ricky Bhatia    schedule 13.03.2019
comment
Этот ответ предназначен для случая нескольких каталогов в одном и том же каталоге, поэтому флаг recursive=True. Это отличается от того, что задает вопрос. - person Vitalis; 16.07.2020