Watch
watch ¶
watch(*paths: Union[Path, str], watch_filter: Optional[Callable[[Change, str], bool]] = DefaultFilter(), debounce: int = 1600, step: int = 50, stop_event: Optional[AbstractEvent] = None, rust_timeout: int = 5000, yield_on_timeout: bool = False, debug: Optional[bool] = None, raise_interrupt: bool = True, force_polling: Optional[bool] = None, poll_delay_ms: int = 300, recursive: bool = True, ignore_permission_denied: Optional[bool] = None) -> Generator[Set[FileChange], None, None]
Watch one or more paths and yield a set of changes whenever files change.
The paths watched can be directories or files, directories are watched recursively - changes in subdirectories are also detected.
Force polling¶
Notify will fall back to file polling if it can't use file system notifications, but we also force Notify
to use polling if the force_polling
argument is True
; if force_polling
is unset (or None
), we enable
force polling thus:
- if the
WATCHFILES_FORCE_POLLING
environment variable exists and is not empty:- if the value is
false
,disable
ordisabled
, force polling is disabled - otherwise, force polling is enabled
- if the value is
- otherwise, we enable force polling only if we detect we're running on WSL (Windows Subsystem for Linux)
It is also possible to change the poll delay between iterations, it can be changed to maintain a good response time
and an appropiate CPU consumption using the poll_delay_ms
argument, we change poll delay thus:
- if file polling is enabled and the
WATCHFILES_POLL_DELAY_MS
env var exists and it is numeric, we use that - otherwise, we use the argument value
Parameters:
Name | Type | Description | Default |
---|---|---|---|
*paths |
Union[Path, str]
|
filesystem paths to watch. |
()
|
watch_filter |
Optional[Callable[[Change, str], bool]]
|
callable used to filter out changes which are not important, you can either use a raw callable
or a |
DefaultFilter()
|
debounce |
int
|
maximum time in milliseconds to group changes over before yielding them. |
1600
|
step |
int
|
time to wait for new changes in milliseconds, if no changes are detected in this time, and at least one change has been detected, the changes are yielded. |
50
|
stop_event |
Optional[AbstractEvent]
|
event to stop watching, if this is set, the generator will stop iteration,
this can be anything with an |
None
|
rust_timeout |
int
|
maximum time in milliseconds to wait in the rust code for changes, |
5000
|
yield_on_timeout |
bool
|
if |
False
|
debug |
Optional[bool]
|
whether to print information about all filesystem changes in rust to stdout, if |
None
|
raise_interrupt |
bool
|
whether to re-raise |
True
|
force_polling |
Optional[bool]
|
See Force polling above. |
None
|
poll_delay_ms |
int
|
delay between polling for changes, only used if |
300
|
recursive |
bool
|
if |
True
|
ignore_permission_denied |
Optional[bool]
|
if |
None
|
Yields:
Type | Description |
---|---|
Set[FileChange]
|
The generator yields sets of |
awatch
async
¶
awatch(*paths: Union[Path, str], watch_filter: Optional[Callable[[Change, str], bool]] = DefaultFilter(), debounce: int = 1600, step: int = 50, stop_event: Optional[AnyEvent] = None, rust_timeout: Optional[int] = None, yield_on_timeout: bool = False, debug: Optional[bool] = None, raise_interrupt: Optional[bool] = None, force_polling: Optional[bool] = None, poll_delay_ms: int = 300, recursive: bool = True, ignore_permission_denied: Optional[bool] = None) -> AsyncGenerator[Set[FileChange], None]
Asynchronous equivalent of watch
using threads to wait for changes.
Arguments match those of watch
except stop_event
.
All async methods use anyio to run the event loop.
Unlike watch
KeyboardInterrupt
cannot be suppressed by awatch
so they need to be caught
where asyncio.run
or equivalent is called.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
*paths |
Union[Path, str]
|
filesystem paths to watch. |
()
|
watch_filter |
Optional[Callable[[Change, str], bool]]
|
matches the same argument of |
DefaultFilter()
|
debounce |
int
|
matches the same argument of |
1600
|
step |
int
|
matches the same argument of |
50
|
stop_event |
Optional[AnyEvent]
|
|
None
|
rust_timeout |
Optional[int]
|
None
|
|
yield_on_timeout |
bool
|
matches the same argument of |
False
|
debug |
Optional[bool]
|
matches the same argument of |
None
|
raise_interrupt |
Optional[bool]
|
This is deprecated, |
None
|
force_polling |
Optional[bool]
|
if true, always use polling instead of file system notifications, default is |
None
|
poll_delay_ms |
int
|
delay between polling for changes, only used if |
300
|
recursive |
bool
|
if |
True
|
ignore_permission_denied |
Optional[bool]
|
if |
None
|
Yields:
Type | Description |
---|---|
AsyncGenerator[Set[FileChange], None]
|
The generator yields sets of |
import asyncio
from watchfiles import awatch
async def main():
async for changes in awatch('./first/dir', './second/dir'):
print(changes)
if __name__ == '__main__':
try:
asyncio.run(main())
except KeyboardInterrupt:
print('stopped via KeyboardInterrupt')
import asyncio
from watchfiles import awatch
async def main():
stop_event = asyncio.Event()
async def stop_soon():
await asyncio.sleep(3)
stop_event.set()
stop_soon_task = asyncio.create_task(stop_soon())
async for changes in awatch('/path/to/dir', stop_event=stop_event):
print(changes)
# cleanup by awaiting the (now complete) stop_soon_task
await stop_soon_task
asyncio.run(main())