pythonpython-watchdog

How to pass an argument to my Python watchdog.events.PatternMatchingEventHandler


I'm quite new to Python and hope the answer to this is obvious to most of you.

I'm creating a class in Python that represents a ScanFolder.

In the __init__ of that class, I start a watchdog.observers

This observer will fire a watchdog.events.PatternMatchingEventHandler whenever a file is changed under the watched directory.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import time

from watchdog.observers import Observer
import watchdog.events

path = sys.argv[1] if len(sys.argv) > 1 else '.'

class MyEventHandler(watchdog.events.PatternMatchingEventHandler):
    def on_any_event(self, event):
        print(event.src_path, event.event_type)

class ScanFolder:
    'Class defining a scan folder'

    def __init__(self, path):
        self.path = path
        self.documents = dict() # key = document label   value = Document reference

        self.event_handler = MyEventHandler(patterns=["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.pdf"],
                                        ignore_patterns=[],
                                        ignore_directories=True)
        self.observer = Observer()
        self.observer.schedule(self.event_handler, self.path, recursive=False)
        self.observer.start()

    def stop(self):
        self.observer.stop()
        self.observer.join()

scan_folder = ScanFolder(path)

try:
    while True:
        time.sleep(1)
        """Here, I'll act on my scan_folder object that lists the discovered files"""
except KeyboardInterrupt:
    log.warning("Ouch !!! Keyboard interrupt received.")

scan_folder.stop()

My problem is the following:

How can I have my scan_folder object modified by my scan_folder.event_handler() ?

Actually, I would like to populate the scan_folder.documents dictionary wherever a file is detected in the scan folder.

Thank you very much and sorry for my ignorance.


Solution

  • There are a lot of way to do it: but the simplest way is set a bound method of ScanFolder as on_any_event callback function of watchdog.events.PatternMatchingEventHandler. So your code become:

    class ScanFolder:
        'Class defining a scan folder'
    
        def __init__(self, path):
            self.path = path
            self.documents = dict() # key = document label   value = Document reference
    
            self.event_handler = watchdog.events.PatternMatchingEventHandler(
                patterns=["*.jpg", "*.jpeg", "*.png", "*.bmp", "*.pdf"],
                ignore_patterns=[],
                ignore_directories=True)
            self.event_handler.on_any_event = self.on_any_event
            self.observer = Observer()
            self.observer.schedule(self.event_handler, self.path, recursive=False)
            self.observer.start()
    
        def on_any_event(self, event):
            print(event.src_path, event.event_type)
            print("Complete ScanFolder() access")
    
        def stop(self):
            self.observer.stop()
            self.observer.join()
    

    Other way could be derive ScanFolder from watchdog.events.PatternMatchingEventHandler .... But injecting function is one of the power of python