Skip to main content

Simple and powerfull file watcher using libc's inotify

Project description

FileWatch

FileWatch is a python library to easily use the libc's inotify functions to watch for any file interaction.

The library aims at being simple yet powerfull with easily auditable code.

Limitations

If you watch a file or a folder for a move it will be unwatched after being moved (renaming is considered a move). This is a limitation of the inotify system which desn't give any way to know the new name/path. Any move/rename within watched folders are kept being tracked, this also works with the recursive option.

When using the recursive option the folder SUB_CREATED and SUB_MOVED events are enforced. Otherwise the watcher would not be able to keep track of the file tree after adding or moving folders.

Install

Use pip or equivalent to install package name watchinotify:

pip install watchinotify

Usage

Create a Watcher and assign its callback to your custom function, then with the Watcher's watch function to add a list (or any iterable) or path to file/folder to watch. The watcher is going to run on a separated thread waiting for any event then calling the callback. You can run your code after calling watch or wait for an event using the threading.Event for instance.

The following example explicits the parameters types of the callback function:

from pathlib import Path
import threading

from watchinotify import Watcher

event_received = threading.Event()

def callback(path: Path | None, event, name: bytes):
    print(f'New event {event} from path {path} with additionnal name {name.decode()}')
    event_received.set()

watcher = Watcher() as watcher:
watcher.watch([Path('/path/to/watch')])
watcher.callback = callback
# Any of your code from here
event_received.wait()

# Do not forget to close the watcher once done (or use a 'with' statement)
watcher.close()

Using a with statement is easier and safer so the close will be automatically called.

with Watcher(event_type, exclude_patterns, recursive) as watcher:  # will automatically close
    watcher.watch([Path('/path/to/watch')])

The Watcher has 3 arguments:

  • event_type : what type of event to watch see the *Event Type section below. If set to None it is using default value of FileEvent.MODIFIED | FileEvent.DELETED | FileEvent.MOVED for files and FolderEvent.DELETED | FolderEvent.MOVED | FolderEvent.SUB_CREATED | FolderEvent.SUB_DELETED | FolderEvent.SUB_MOVED for folders. You can use the parent Event type to set all required events, if you want specific events separated it is better to create multiple watchers. Default: None
  • exclude_patterns : iterable (list, tuple, etc) of pattern to ignore,following glob conventions, example : ['*/sub_folder', __pycache__]. Default: None
  • recursive : boolean to watch recursively all sub folders/files when adding a folder to watch. This will force the events FolderEvent.SUB_CREATED and FolderEvent.SUB_MOVED to be watched in order to properly work, you'll have to filter out those event in you callback if unwanted. Default: True

Event Types

All possible events are un the Event flag. You can cumulate events by using the or or | operator. 2 additionnal types FileEvent and FolderEvent inherits from the Event values but only contains the event that can be trigger respectively from files and folders. The 2 sub types also have an ALL value as a handy shortcut.

The events are defined as:

from enum import IntFlag, auto

class Event(IntFlag):
    OPENED = auto()
    MODIFIED = auto()
    DELETED = auto()
    MOVED = auto()
    CLOSED = auto()
    SUB_CREATED = auto()
    SUB_DELETED = auto()
    SUB_MOVED = auto()


class FileEvent(IntFlag):
    OPENED = Event.OPENED.value
    MODIFIED = Event.MODIFIED.value
    DELETED = Event.DELETED.value
    MOVED = Event.MOVED.value
    CLOSED = Event.CLOSED.value

    ALL = OPENED | MODIFIED | DELETED | MOVED | CLOSED


class FolderEvent(IntFlag):
    DELETED = Event.DELETED.value
    MOVED = Event.MOVED.value
    SUB_CREATED = Event.SUB_CREATED.value
    SUB_DELETED = Event.SUB_DELETED.value
    SUB_MOVED = Event.SUB_MOVED.value

    ALL = DELETED | MOVED | SUB_CREATED | SUB_DELETED | SUB_MOVED

Development

Run test

pytest

Run coverage

python tests/run_coverage.py

LICENSE

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

watchinotify-0.1.0.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

watchinotify-0.1.0-py3-none-any.whl (19.9 kB view details)

Uploaded Python 3

File details

Details for the file watchinotify-0.1.0.tar.gz.

File metadata

  • Download URL: watchinotify-0.1.0.tar.gz
  • Upload date:
  • Size: 24.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for watchinotify-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c944c8075a2d5193b3db0558f2e96ac7948d0a866191442e199be881a42e5668
MD5 d61b55879356b064bab44a07bb6e18b8
BLAKE2b-256 b01040655da2f7d8c2cc0f338440435bdd187ba6a70304f08f3a79206b9206e5

See more details on using hashes here.

File details

Details for the file watchinotify-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: watchinotify-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 19.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for watchinotify-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 534b1e69d2ff8930c8c7c656a24d5d4e0fb6052cce464ae9f9d772f91cb4444b
MD5 ff8aa4cf2519a33e9020b4b07abb2f03
BLAKE2b-256 ecc8c89fa76a7ec95bbbe78a68e474dbab87fcaa1c7c87117acdcc1c3f89443b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page