Skip to main content

watchgod

CI Coverage pypi license

Simple, modern file watching and code reload in python.


NOTICE - Package Renamed to watchfiles

Please note: This package (watchgod) has been renamed to watchfiles. Please replace watchgod with watchfiles, see the migration guide for help and instructions on switching.

As well as a better name, watchfiles has a whole new backend based on rust-notify which makes watching for filesystem events much more efficient.

The package under the name watchgod will not be further developed and will only receive critical security fixes.


Usage

To watch for changes in a directory:

from watchgod import watch

for changes in watch('./path/to/dir'):
    print(changes)

To run a function and restart it when code changes:

from watchgod import run_process

def foobar(a, b, c):
    ...

run_process('./path/to/dir', foobar, args=(1, 2, 3))

run_process uses PythonWatcher so only changes to python files will prompt a reload, see custom watchers below.

If you need notifications about change events as well as to restart a process you can use the callback argument to pass a function which will be called on every file change with one argument: the set of file changes.

Installation

pip install watchgod

Asynchronous Methods

watchgod comes with an asynchronous equivalents of watch: awatch which uses a ThreadPoolExecutor to iterate over files.

import asyncio
from watchgod import awatch

async def main():
    async for changes in awatch('/path/to/dir'):
        print(changes)

asyncio.run(main())

There's also an asynchronous equivalents of run_process: arun_process which in turn uses awatch:

import asyncio
from watchgod import arun_process

def foobar(a, b, c):
    ...

async def main():
    await arun_process('./path/to/dir', foobar, args=(1, 2, 3))

asyncio.run(main())

arun_process uses PythonWatcher so only changes to python files will prompt a reload, see custom watchers below.

The signature of arun_process is almost identical to run_process except that the optional callback argument must be a coroutine, not a function.

Custom Watchers

watchgod comes with the following watcher classes which can be used via the watcher_cls keyword argument to any of the methods above.

For example:

for changes in watch(directoryin, watcher_cls=RegExpWatcher, watcher_kwargs=dict(re_files=r'^.*(\.mp3)$')):
   print (changes)

For more details, checkout watcher.py, it's pretty simple.

  • AllWatcher The base watcher, all files are checked for changes.

  • DefaultWatcher The watcher used by default by watch and awatch, commonly ignored files like *.swp, *.pyc and *~ are ignored along with directories like .git.

  • PythonWatcher Specific to python files, only *.py, *.pyx and *.pyd files are watched.

  • DefaultDirWatcher Is the base for DefaultWatcher and DefaultDirWatcher. It takes care of ignoring some regular directories.

If these classes aren't sufficient you can define your own watcher, in particular you will want to override should_watch_dir and should_watch_file. Unless you're doing something very odd, you'll want to inherit from DefaultDirWatcher.

Note that events related to directories are not reported (e.g. creation of a directory), but new files in new directories will be reported.

CLI

watchgod also comes with a CLI for running and reloading python code.

Lets say you have foobar.py:

from aiohttp import web

async def handle(request):
    return web.Response(text='testing')

app = web.Application()
app.router.add_get('/', handle)

def main():
    web.run_app(app, port=8000)

You could run this and reload it when any file in the current directory changes with::

watchgod foobar.main

In case you need to ignore certain files or directories, you can use the argument --ignore-paths.

Run watchgod --help for more options. watchgod is also available as a python executable module via python -m watchgod ....

Why no inotify / kqueue / fsevent / winapi support

watchgod (for now) uses file polling rather than the OS's built in file change notifications.

This is not an oversight, it's a decision with the following rationale:

  1. Polling is "fast enough", particularly since PEP 471 introduced fast scandir. For reasonably large projects like the TutorCruncher code base with 850 files and 300k lines of code, watchgod can scan the entire tree in ~24ms. With a scan interval of 400ms that is roughly 5% of one CPU - perfectly acceptable load during development.
  2. The clue is in the title, there are at least 4 different file notification systems to integrate with, most of them not trivial. That is all before we get to changes between different OS versions.
  3. Polling works well when you want to group or "debounce" changes. Let's say you're running a dev server and you change branch in git, 100 files change. Do you want to reload the dev server 100 times or once? Right. Polling periodically will likely group these changes into one event. If you're receiving a stream of events you need to delay execution of the reload when you receive the first event to see if it's part of a group of file changes. This is not trivial.

All that said, I might still use rust's "notify" crate to do the heavy lifting of file watching, see#25.

Release files for watchgod 0.8.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for watchgod 0.8.2
File Size Uploaded
watchgod-0.8.2.tar.gz 13.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for watchgod 0.8.2
File Interpreter ABI Platform
watchgod-0.8.2-py3-none-any.whl Python 3 none any Details

Total release size: 26.1 kB

Release files / watchgod-0.8.2.tar.gz

Download URL watchgod-0.8.2.tar.gz
Size 13.9 kB
Tags Source
SHA-256 checksum
How to use checksums
cb11ff66657befba94d828e3b622d5fb76f22fbda1376f355f3e6e51e97d9450
BLAKE2b-256 checksum
How to use checksums
e86e3904af0715e03fc5b2636cb8cf8b0eabc45b1f2cf6e4cf8453ddb6d23042
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.0 CPython/3.9.10

Release files / watchgod-0.8.2-py3-none-any.whl

Download URL watchgod-0.8.2-py3-none-any.whl
Size 12.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2f3e8137d98f493ff58af54ea00f4d1433a6afe2ed08ab331a657df468c6bfce
BLAKE2b-256 checksum
How to use checksums
9f60cfd9150167cb8ec0ac07642fe1383d27300729e0b2b877ff89cb0862bbeb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/4.0.0 CPython/3.9.10

Release history Release notifications | RSS feed

This release

0.8.2 This release

2 release files

0.8.1

2 release files

0.8

2 release files

0.7

2 release files

0.6

2 release files

0.5

2 release files

0.4

2 release files

0.3

2 release files

0.2

2 release files

0.1.1

2 release files

0.1

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page