DEV Community

Cover image for Monitor files for changes with Python
Stokry
Stokry

Posted on • Edited on

Monitor files for changes with Python

Today I want to show how can you monitor changes of a directory with watchdog. It is a Python module that monitors our filesystem looking for any changes (like the creation, change, or deletion of a file or of a directory). When a change occurs, the watchdog reports it to us via specific event that we can handle. So for example, if you need to watch a log file for changes this module is perfect, or if you had a configuration file that is been changed you can also use this module to track that.

First of all, you need to install Watchdog via pip:

pip install watchdog
Enter fullscreen mode Exit fullscreen mode

After that we need to make import

import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
Enter fullscreen mode Exit fullscreen mode

After that we need to create an event handler, basically is the object that will be notified when something happens on the folder that we are monitoring. Also we need another object, known as the observer, that will monitor our filesystem, looking for changes that will be handled by the event handler.

if __name__ ==  "__main__":
   event_handler = MyHandler()
   observer = Observer()
   observer.schedule(event_handler,  path='C:\\Users\\Stokry\Desktop\\test',  recursive=False)
   observer.start()
Enter fullscreen mode Exit fullscreen mode

Now that we have created the handler and observer we need to write the code we want to run when the events occur.
Let’s start creating three different functions that will be used when a file is modified, created, or deleted. We can also add function when something is moved.

class  MyHandler(FileSystemEventHandler):
    def  on_modified(self,  event):
         print(f'event type: {event.event_type} path : {event.src_path}')
    def  on_created(self,  event):
         print(f'event type: {event.event_type} path : {event.src_path}')
    def  on_deleted(self,  event):
         print(f'event type: {event.event_type} path : {event.src_path}')
Enter fullscreen mode Exit fullscreen mode

Putting all together:

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

class  MyHandler(FileSystemEventHandler):
    def  on_modified(self,  event):
         print(f'event type: {event.event_type} path : {event.src_path}')
    def  on_created(self,  event):
         print(f'event type: {event.event_type} path : {event.src_path}')
    def  on_deleted(self,  event):
         print(f'event type: {event.event_type} path : {event.src_path}')

if __name__ ==  "__main__":
    event_handler = MyHandler()
    observer = Observer()
    observer.schedule(event_handler,  path='C:\\Users\\Stokry\Desktop\\test',  recursive=False)
    observer.start()

     try:
        while  True:
            time.sleep(1)
     except  KeyboardInterrupt:
        observer.stop()
     observer.join()
Enter fullscreen mode Exit fullscreen mode

Now we can test this out.
Let's say we delete the file, the output is like this:

event type: deleted path : C:\Users\Stokry\Desktop\test\log_old.txt
Enter fullscreen mode Exit fullscreen mode

Thank you all.

Top comments (3)

Collapse
 
eorojas profile image
Emilio Rojas

Does the code require the sleep? If not, it should be doing some other sort of work. Perhaps putting an event in a queue and waiting on that.

Collapse
 
stokry profile image
Stokry • Edited

Yes, the time.sleep(1) is used to keep the program running in a loop, continuously checking for filesystem events. Without this sleep, the program would exit immediately, and the observer would not have a chance to detect any events. However, I agree that the code could be enhanced to utilize a more event-driven approach rather than a simple sleep. An alternative approach could involve using an event queue and waiting for an event to be added to the queue, but in this particular context, the sleep function serves the purpose of keeping the application alive without adding unnecessary complexity.

Collapse
 
ipapop profile image
ipapop

Thank You for this interesting post. I am also trying to achieve more without JavaScript.

When writing a new app you don't necessarily want to deploy a flask framework just to test your ideas.Since you can not easily pass variables between JavaScript and Python one way to achieve this is to create a JSON file from a JavaScript HTML element and read the JSON file from your python app. This is where I needed a way to detect a JSON file change. Your post came in really handy for me.

I am just wondering about the additional machine workload induced by the monitoring though..