TechA
TechA

Reputation: 1

Watchdog run function once

Below is my watchdog script. When a file is modified in Vim, the deleted then created events are fired. This is expected.

This leads to the problem. I would like it to ignore the deleted event on file modification with Vim and run the modified function, but run the deleted function when a file is actually deleted.

Is this possible without changing my Vim config?

import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

WATCH_PATH = './files'

class Handler(FileSystemEventHandler):
    def on_any_event(self, event):
        if event == 'modified':
            modified(event.src_path)
        if event == 'created':
            created(event.src_path)
        if event == 'deleted':
            deleted(event.src_path)

def modified(src):
    print(src, 'modified')

def created(src):
    print(src, 'created')

def deleted(src):
    print(src, 'deleted')

if __name__ == "__main__":
    eh = Handler()
    observer = Observer()
    observer.schedule(eh, path=WATCH_PATH, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

Log

2020-04-26 03:47:02 - Deleted file: ./files/a.txt
2020-04-26 03:47:02 - Modified directory: ./files
2020-04-26 03:47:10 - Created file: ./files/a.txt
2020-04-26 03:47:10 - Modified directory: ./files

Vim

Vim is configured so that temporary files are not stored in the working directory.

Upvotes: 0

Views: 1237

Answers (1)

AKA
AKA

Reputation: 594

To understand the problem better, I have modified your code a little bit.

...
from watchdog.events import FileSystemEventHandler, LoggingEventHandler
...

if __name__ == "__main__":
  # eh = Handler()
  eh = LoggingEventHandler()

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

  observer = Observer()
  ...

Replacing FileSystemEventHandler with LoggingEventHandler in the main function, it will generates the log of the events. On modifying a text file in the directory './file' , logs generated as follows:

2020-04-26 12:41:25 - Created file: ./files/b.txt~
2020-04-26 12:41:25 - Modified directory: ./files
2020-04-26 12:41:25 - Modified file: ./files/b.txt~
2020-04-26 12:41:25 - Modified file: ./files/b.txt
2020-04-26 12:41:25 - Modified file: ./files/b.txt
2020-04-26 12:41:25 - Deleted file: ./files/b.txt~
2020-04-26 12:41:25 - Modified directory: ./files

Here the deleted file is the b.txt~ which is the intermediate file and not your original file. So you just need to filter out the events of intermediate files.

Here is the code with the fix:

import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler, LoggingEventHandler

WATCH_PATH = './files'

class Handler(FileSystemEventHandler):

    def on_any_event(self, event):

        if str(event.src_path).endswith("~"):
            return None

        if event.event_type == 'modified':
            modified(event.src_path)
        elif event.event_type == 'created':
            created(event.src_path)
        elif event.event_type == 'deleted':
            deleted(event.src_path)

def modified(src):
    print(src, 'modified')

def created(src):
    print(src, 'created')

def deleted(src):
    print(src, 'deleted')

if __name__ == "__main__":
    eh = Handler()

    observer = Observer()
    observer.schedule(eh, path=WATCH_PATH, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        print("Stopping the observer...")
        observer.stop()
    observer.join()

Output:

./files modified
./files/b.txt modified
./files modified

Upvotes: 1

Related Questions