Python Watchdog File Monitoring — Core Concepts
What Watchdog does
Watchdog is a Python library that monitors filesystem changes and triggers callbacks when files or directories are created, modified, deleted, or moved. Instead of polling a directory in a loop (“has anything changed? how about now?”), Watchdog hooks into operating system APIs that notify your program the instant something happens.
The core components
Observer
The Observer is the background thread that watches the filesystem. You create one, tell it what directory to watch, and start it:
from watchdog.observers import Observer
observer = Observer()
observer.schedule(my_handler, path="/data", recursive=True)
observer.start()
The recursive=True flag means it watches subdirectories too. The observer runs in its own thread, so your main program can continue doing other things.
Event handler
An event handler defines what happens when a file changes. You subclass FileSystemEventHandler and override the methods you care about:
from watchdog.events import FileSystemEventHandler
class MyHandler(FileSystemEventHandler):
def on_created(self, event):
print(f"New file: {event.src_path}")
def on_modified(self, event):
print(f"Changed: {event.src_path}")
def on_deleted(self, event):
print(f"Deleted: {event.src_path}")
def on_moved(self, event):
print(f"Moved: {event.src_path} → {event.dest_path}")
Each method receives an event object with the file path and whether it is a file or directory.
Event types
Watchdog fires four event types:
- Created — a new file or directory appears
- Modified — file contents or metadata change
- Deleted — a file or directory is removed
- Moved — a file or directory is renamed or relocated
Each event also has an is_directory flag so you can filter file events from directory events.
How it works under the hood
Watchdog uses different backends depending on the operating system:
- Linux —
inotify(kernel-level file notification) - macOS —
FSEvents(Apple’s filesystem event stream) - Windows —
ReadDirectoryChangesW(Win32 API) - Fallback — polling (checking every N seconds)
The native backends are efficient because the OS kernel does the watching. Your program uses almost no CPU while waiting. The polling fallback works everywhere but uses more resources and has a delay between changes and detection.
A complete working example
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class LogHandler(FileSystemEventHandler):
def on_modified(self, event):
if event.src_path.endswith(".log"):
print(f"Log updated: {event.src_path}")
# Process the new log entries here
observer = Observer()
observer.schedule(LogHandler(), path="/var/log/myapp", recursive=False)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
This watches a log directory and reacts only to .log file changes. The time.sleep(1) loop keeps the main thread alive while the observer does its work in the background.
Pattern matching
Watchdog provides PatternMatchingEventHandler for filtering by file extension or name:
from watchdog.events import PatternMatchingEventHandler
handler = PatternMatchingEventHandler(
patterns=["*.csv", "*.json"],
ignore_patterns=["*.tmp"],
ignore_directories=True,
)
This handler only fires for CSV and JSON files, ignoring temporary files and directory events.
Common misconception
A frequent mistake is assuming Watchdog detects content-level changes. It does not read file contents — it only knows that a file was modified at the OS level. If you need to know what changed inside a file, you need to track the previous content yourself and compute a diff when the modification event fires.
Real-world uses
- Development servers — frameworks like Django and Flask use file watchers to auto-reload when code changes
- Data pipelines — watch an inbox folder for new CSV files and process them automatically
- Backup systems — detect changes and sync modified files to cloud storage
- Log monitoring — tail log files and trigger alerts on specific patterns
The one thing to remember: Watchdog gives your Python program OS-level eyes on the filesystem, triggering instant callbacks when files change so you never have to poll in a loop.
See Also
- Python Fabric Remote Execution Run commands on faraway computers from your desk using Python Fabric — like a universal remote for servers.
- Python Invoke Task Runner Automate boring computer chores with Python Invoke — like teaching your computer a recipe book of tasks.
- Python Netmiko Network Automation Talk to routers and switches with Python Netmiko — like a translator that speaks every network device's language.
- Python Schedule Task Scheduling Make Python run tasks on a timer — like setting an alarm clock for your code.
- Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.