Tricks & Advanced Configuration#
A trick is a configurable filesystem event handler. Built-in tricks can log events, execute shell commands, or restart processes, and you can create your own by subclassing watchdog.tricks.Trick.
The watchmedo tricks command loads one or more event handlers (“tricks”) from a configuration file and runs them under a single filesystem observer. Every configured trick receives matching filesystem events from the same observer.
It is designed for complex or multi-step pipelines where you want to perform multiple actions for filesystem events (such as logging, executing commands, and restarting processes simultaneously) without running multiple separate watchmedo commands in different terminal windows, or writing a custom Python application.
The Concept#
Without tricks, running multiple tasks requires starting several terminal processes, each running its own observer:
# Terminal 1
watchmedo log --patterns="*.py" .
# Terminal 2
watchmedo shell-command --patterns="*.py" --command="ruff check ." .
# Terminal 3
watchmedo auto-restart --patterns="*.py" --command="python app.py" .
Using tricks simplifies configuration by allowing multiple event handlers to run under a single observer:
Filesystem
│
One Observer
│
┌──────────┼──────────┐
│ │ │
LoggerTrick ShellCommand CustomTrick
Tricks Command#
To run tricks, you specify a configuration file. The examples below use YAML, but the same configuration can also be provided as JSON:
$ watchmedo tricks tricks.yaml
Generating a Trick Template#
To quickly get a template YAML file detailing the syntax for all available built-in tricks, run:
$ watchmedo generate-tricks-yaml > tricks.yaml
Configuration Format#
Tip
The configuration keys for each trick in the YAML file map directly to the constructor arguments (__init__ parameters) of the corresponding Python class (e.g. ShellCommandTrick). They are conceptually identical to the command-line flags used in the direct CLI commands (for example, wait_for_process in YAML corresponds to the --wait CLI option).
Here is a typical tricks.yaml configuration file demonstrating how to combine the built-in logger and shell-command tricks:
tricks:
- watchdog.tricks.LoggerTrick:
patterns: ["*.py", "*.txt"]
ignore_directories: true
- watchdog.tricks.ShellCommandTrick:
patterns: ["*.py"]
shell_command: "echo 'file changed: ${watch_src_path}'"
wait_for_process: true
Writing Custom Tricks#
In addition to the built-in tricks, you can create your own by subclassing watchdog.tricks.Trick and referencing it directly in your YAML configuration.
Write the custom trick class in Python:
# mypackage/tricks.py from watchdog.tricks import Trick class NotifyTeamTrick(Trick): def on_modified(self, event): # Perform custom validation, Slack alert, or cache update print(f"Notifying team about: {event.src_path}")
Reference the custom trick in your configuration file:
tricks: - mypackage.tricks.NotifyTeamTrick: patterns: ["*.yaml"]
Tricks Module Reference#
Tricks are pre-implemented, configurable event handlers that subclass watchdog.tricks.Trick (which itself subclasses watchdog.events.PatternMatchingEventHandler).
You can reference and configure these tricks in your YAML files or instantiate them directly in your Python code:
- class watchdog.tricks.Trick(*, patterns: list[str] | None = None, ignore_patterns: list[str] | None = None, ignore_directories: bool = False, case_sensitive: bool = False)[source]
Your tricks should subclass this class.
- class watchdog.tricks.LoggerTrick(*, patterns: list[str] | None = None, ignore_patterns: list[str] | None = None, ignore_directories: bool = False, case_sensitive: bool = False)[source]
A simple trick that does only logs events.
- class watchdog.tricks.ShellCommandTrick(shell_command: str, *, patterns: list[str] | None = None, ignore_patterns: list[str] | None = None, ignore_directories: bool = False, wait_for_process: bool = False, drop_during_process: bool = False)[source]
Executes shell commands in response to matched events.
- Parameters:
shell_command – The shell command to execute.
patterns – Matches event paths with these patterns.
ignore_patterns – Ignores event paths with these patterns.
ignore_directories – Ignores events for directories (default: False).
wait_for_process – Wait for process to finish to avoid multiple simultaneous instances.
drop_during_process – Ignore events that occur while command is still being executed to avoid multiple simultaneous instances.
- class watchdog.tricks.AutoRestartTrick(command: list[str], *, patterns: list[str] | None = None, ignore_patterns: list[str] | None = None, ignore_directories: bool = False, stop_signal: Signals | int = Signals.SIGINT, kill_after: int = 10, debounce_interval_seconds: int = 0, restart_on_command_exit: bool = True)[source]
Starts a long-running subprocess and restarts it on matched events.
The command parameter is a list of command arguments, such as [‘bin/myserver’, ‘-c’, ‘etc/myconfig.ini’].
Call start() after creating the Trick. Call stop() when stopping the process.
- Parameters:
command – The long-running command to run and restart.
patterns – Matches event paths with these patterns.
ignore_patterns – Ignores event paths with these patterns.
ignore_directories – Ignores events for directories (default: False).
stop_signal – Stop the subprocess with this signal (default SIGINT).
kill_after – When stopping, kill the subprocess after the specified timeout in seconds (default 10.0).
debounce_interval_seconds – After a file change, wait until the specified interval (in seconds) passes with no file changes, and only then restart (default: 0.0).
restart_on_command_exit – Auto-restart the command after it exits (default: True).