pyinotify
pyinotify is a Python library that provides a straightforward interface to the Linux kernel's inotify subsystem. It allows applications to monitor filesystem events like file creation, deletion, modification, and access in a given directory or hierarchy. The current version is 0.9.6, released in 2015. The project has since been in a maintenance mode with occasional updates to ensure Python compatibility, rather than active feature development.
Warnings
- breaking `pyinotify` is inherently Linux-specific, as it directly interfaces with the `inotify` kernel subsystem. It will not work on other operating systems like macOS or Windows, and attempting to use it will result in errors.
- gotcha The `notifier.loop()` method is blocking and will prevent the rest of your application from executing. If you need non-blocking behavior (e.g., in a GUI application or when integrating with `asyncio`), you must use `notifier.process_events()` with a timeout within your own event loop or a separate thread.
- gotcha If events are generated faster than they can be processed, the kernel's inotify event queue can overflow, leading to missed events. The default queue size is usually limited (e.g., 16384 events).
- gotcha Misunderstanding `wm.add_watch()` flags like `rec=True` (recursive) and `auto_add=True` can lead to unintended behavior, such as watching too many files/directories, or missing events for newly created directories that weren't explicitly watched.
Install
-
pip install pyinotify
Imports
- WatchManager
import pyinotify wm = pyinotify.WatchManager()
- Notifier
import pyinotify notifier = pyinotify.Notifier(wm, event_handler)
- ProcessEvent
import pyinotify class MyHandler(pyinotify.ProcessEvent): ...
Quickstart
import pyinotify
import os
import time
# Create a temporary directory for demonstration
watch_dir = "/tmp/pyinotify_example_dir"
os.makedirs(watch_dir, exist_ok=True)
print(f"Watching directory: {watch_dir}")
print("Try 'touch {watch_dir}/file1' or 'rm {watch_dir}/file1'")
print("Press Ctrl+C to stop.")
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
print(f"Created: {event.pathname}")
def process_IN_DELETE(self, event):
print(f"Deleted: {event.pathname}")
wm = pyinotify.WatchManager()
mask = pyinotify.IN_CREATE | pyinotify.IN_DELETE
# Attach the WatchManager and EventHandler to a Notifier
notifier = pyinotify.Notifier(wm, EventHandler())
# Add a watch to the directory for the specified events
# rec=True ensures subdirectories are also watched
wm.add_watch(watch_dir, mask, rec=True)
try:
# Start processing events. This method blocks indefinitely.
# For non-blocking, use notifier.process_events() in a custom loop.
notifier.loop()
except KeyboardInterrupt:
print("\nStopping watcher.")
finally:
notifier.stop() # Clean up inotify resources
# Clean up the example directory
if os.path.exists(watch_dir):
# Ensure directory is empty before removing
for root, dirs, files in os.walk(watch_dir, topdown=False):
for name in files:
os.remove(os.path.join(root, name))
for name in dirs:
os.rmdir(os.path.join(root, name))
os.rmdir(watch_dir)