{"id":4578,"library":"inotify-simple","title":"inotify-simple","description":"inotify-simple is a lightweight Python wrapper around the Linux `inotify` API, implemented using `ctypes`. It provides a direct, low-level interface to filesystem events without much abstraction, making it efficient and close to the kernel's behavior. The library is currently at version 2.0.1 and is actively maintained with a stable release cadence.","status":"active","version":"2.0.1","language":"en","source_language":"en","source_url":"https://github.com/chrisjbillington/inotify_simple.git","tags":["inotify","linux","filesystem","events","wrapper","ctypes","low-level"],"install":[{"cmd":"pip install inotify-simple","lang":"bash","label":"Install stable release"}],"dependencies":[{"reason":"Requires Python 3.6 or higher for execution.","package":"python","optional":false}],"imports":[{"note":"Main class for interacting with the inotify file descriptor.","symbol":"INotify","correct":"from inotify_simple import INotify"},{"note":"Enum containing inotify event flags (e.g., CREATE, MODIFY, DELETE).","symbol":"flags","correct":"from inotify_simple import flags"},{"note":"Namedtuple returned by INotify.read() representing a filesystem event.","symbol":"Event","correct":"from inotify_simple import Event"}],"quickstart":{"code":"import os\nimport time\nfrom inotify_simple import INotify, flags\n\n# Create a temporary directory to watch\nwatch_dir = '/tmp/inotify_test_simple'\nos.makedirs(watch_dir, exist_ok=True)\n\ninotify = INotify()\n\n# Add a watch for create, delete, and modify events\n# flags.CLOSE_WRITE is often useful for 'file saved' events\nwatch_flags = flags.CREATE | flags.DELETE | flags.MODIFY | flags.CLOSE_WRITE\nwd = inotify.add_watch(watch_dir, watch_flags)\n\nprint(f\"Watching directory: {watch_dir} (watch descriptor: {wd})\")\nprint(\"Create, modify, or delete files in this directory. Press Ctrl+C to exit.\")\n\ntry:\n    while True:\n        # Read events with a timeout (e.g., 1000 ms = 1 second)\n        # Events are returned as a list of namedtuple objects\n        events = inotify.read(timeout=1000)\n        if not events:\n            # print(\"No events in the last second.\") # Uncomment for verbose output\n            continue\n\n        for event in events:\n            print(f\"Event: wd={event.wd}, mask={event.mask} ({flags.from_mask(event.mask)}), cookie={event.cookie}, name='{event.name}'\")\n\n            # Example: react to a file creation\n            if flags.CREATE in flags.from_mask(event.mask):\n                print(f\"  New file/directory created: {os.path.join(watch_dir, event.name)}\")\n            if flags.DELETE in flags.from_mask(event.mask):\n                print(f\"  File/directory deleted: {os.path.join(watch_dir, event.name)}\")\n            if flags.CLOSE_WRITE in flags.from_mask(event.mask):\n                print(f\"  File written and closed: {os.path.join(watch_dir, event.name)}\")\n\nexcept KeyboardInterrupt:\n    print(\"Monitoring stopped.\")\nfinally:\n    inotify.rm_watch(wd)\n    inotify.close()\n    # Clean up the temporary directory\n    # os.rmdir(watch_dir) # Only if empty\n    print(f\"Removed watch for {watch_dir} and closed inotify instance.\")\n","lang":"python","description":"This example demonstrates how to set up a basic `inotify` watch on a directory for creation, deletion, modification, and close-write events. It then continuously reads and prints detected events. It also shows how to gracefully stop the monitoring and clean up resources."},"warnings":[{"fix":"Implement logic to recursively add watches for new and existing subdirectories. Continuously scan for new directories if full recursive monitoring is required.","message":"inotify, and by extension `inotify-simple`, does not recursively monitor subdirectories. To monitor an entire directory tree, you must explicitly add watches for each subdirectory. New subdirectories created after the initial setup will also require new watches to be added programmatically.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Set a `timeout` argument in `INotify.read()` or wrap the `INotify` instance with `select.select()` or an `asyncio` event loop to handle concurrent I/O operations.","message":"The `INotify.read()` method is blocking by default when `timeout` is `None` or negative. If your application needs to perform other tasks while waiting for events, use a non-blocking approach (e.g., `timeout=0` or a positive timeout) or integrate with `select.select()`/`selectors` to monitor multiple file descriptors, including the `inotify` instance.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Increase kernel limits (`sysctl -w fs.inotify.max_queued_events=...`). Design event processing to be as fast as possible to minimize queue backlog, or implement a recovery strategy (e.g., rescan monitored directories) if an overflow event (`flags.Q_OVERFLOW`) is received.","message":"The kernel's `inotify` event queue has a limited size (`/proc/sys/fs/inotify/max_queued_events`). If events are generated faster than they are consumed by the application, the queue can overflow, leading to lost events. Robust applications should anticipate and handle this possibility.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Maintain a dictionary mapping watch descriptors (`wd`) to full paths. When processing events, use the `wd` to retrieve the most current path from your cache, and be prepared for the `name` field to be outdated or point to a non-existent file.","message":"`inotify` events are reported with a watch descriptor (`wd`) and a `name` (filename). The `name` field might refer to a file that has already been deleted or renamed by the time the event is processed. It is the application's responsibility to maintain a mapping between `wd`s and current file paths if needed, and to handle stale `name` references.","severity":"gotcha","affected_versions":"All versions"},{"fix":"If user/process attribution or network filesystem monitoring is required, `inotify-simple` is not the right tool. Consider auditing solutions or higher-level network file system APIs.","message":"The `inotify` API does not provide information about the user or process that triggered a filesystem event. All events appear to originate from the kernel. Also, it does not monitor events on network filesystems.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-12T00:00:00.000Z","next_check":"2026-07-11T00:00:00.000Z"}