A simple Python hot-reloading tool that automatically reloads modules and scripts when they change, inspired by jurigged and built on watchdog.
- Hot Reloading: Automatically reloads Python code when files change
- State Preservation: Patches existing objects in-place, preserving application state
- Module Support: Works with scripts, modules, and packages
- Selective Reloading: Only reloads changed code chunks (functions, classes, statements)
- Smart Detection: Uses AST parsing to identify and reload individual code components
- Script Mode: Run and reload Python scripts
- Module Mode: Execute modules with
-mflag - Function Mode: Run specific functions from modules
- Code Mode: Execute code snippets with
-cflag - Interactive Mode: Drop into interactive console after execution with
-i - Loop Mode: Continuously re-execute code on changes with
-l - Daemon Mode: Run reloader in background thread
- Watch Additional Paths: Monitor extra files/directories with
-w - Clear Screen: Clear terminal before each reload with
-C - Debouncing: Configurable delay to batch rapid file changes
- Interrupt Handling: Gracefully interrupt long-running code during reload
- Path Filtering: Exclude system paths from reloading
- Import System Integration: Hooks into Python's import system via MetaPathFinder
- Concurrent Monitoring: Efficiently monitors multiple files using watchdog
- AST-Based Parsing: Parses code into reloadable chunks
- Function Patching: Updates
__code__,__doc__,__annotations__,__defaults__ - Class Patching: Preserves class instances while updating methods
- Execution Tracking: Maintains counters to determine what needs reloading
- Syntax Error Handling: Gracefully handles syntax errors without crashing
pip install reloader.py# Run a script with auto-reload
python -m reloader script.py
# Run with loop mode (continuously re-executes)
python -m reloader -l script.py
# Run a module
python -m reloader -m module_name
# Run a specific function
python -m reloader -m module_name:function_name
# Execute code snippet
python -m reloader -c "print('Hello, World!')"
# Interactive mode after execution
python -m reloader -i script.py# Watch additional directories
python -m reloader -l -w /path/to/watch script.py
# Clear screen before each reload
python -m reloader -l -C script.py
# Custom debounce interval (seconds)
python -m reloader -d 0.5 script.py
# Run with arguments
python -m reloader script.py arg1 arg2
# Combine multiple options
python -m reloader -l -C -w ./config -w ./templates app.py| Option | Long Form | Description |
|---|---|---|
-i |
--interactive |
Enter interactive mode after script execution |
-c |
--code |
Execute code string instead of script |
-m |
--module |
Run module (optionally with :function) |
-l |
--loop |
Enable loop mode for continuous execution |
-w |
--watch |
Watch additional paths (requires --loop) |
-C |
--clear |
Clear screen before each reload |
-d |
--debounce |
Set debounce interval in seconds (default: 0.1) |
-P |
--no-cwd-python-path |
Don't add current directory to Python path |
--disallowed-path-types |
Exclude path types from reloading | |
--allowed-path-types |
Include specific path types for reloading | |
--version |
Show version information |
- File Monitoring: Uses watchdog to monitor file system events
- Code Parsing: Parses Python files into AST to identify code chunks
- Change Detection: Compares old and new code to find modifications
- Hot Patching: Updates existing objects without replacing them
- Execution: Re-executes changed code while preserving state
- Watcher: Monitors file system changes using watchdog
- CodeModule: Represents a Python module that can be reloaded
- CodeChunk: Individual piece of code (function, class, or statement)
- ModulePatcher: Handles the complex logic of patching existing objects
- Reloader: Reload engine that applies file changes to watched modules
LoopReloader: Re-executes the target after each change (interrupting long-running scripts)DaemonReloader: Runs the target once in the foreground while reloading in a daemon thread
ScriptTarget: Runs a script file or module as__main__FuncTarget: Runs a specific function from a moduleCodeTarget: Evaluates a compiled code snippet (-c)ConsoleTarget: Runs an interactive console (-i)
- Cannot reload certain built-in types (e.g., MemberDescriptor)
- Changes to function signatures may require restart
- Some module-level state may not be preserved perfectly
- Threading and async code may have edge cases
Built with:
- Python 3.12+
- watchdog for file monitoring
- AST for code analysis
- Threading for concurrent operations
MIT License
Inspired by jurigged and built on watchdog.
Author: EcmaXp