Make Django’s autoreloader more efficient by watching for changes with watchfiles.
Project description
Make Django’s autoreloader more efficient by watching for changes with watchfiles.
Improve your Django and Git skills with my books.
Requirements
Python 3.9 to 3.14 supported.
Django 4.2 to 6.0 supported.
Installation
Install with pip:
python -m pip install django-watchfilesAdd django-watchfiles to your INSTALLED_APPS:
INSTALLED_APPS = [ ..., "django_watchfiles", ..., ]
That’s it! 😅
Try installing django-browser-reload as well, to make your browser automatically reload the page when changes are detected.
Usage
django-watchfiles will be automatically used by Django’s runserver command. You can tell this because runserver will list WatchfilesReloader as the watcher class:
$ ./manage.py runserver
Watching for file changes with WatchfilesReloader
...
(Rather than the default StatReloader.)
WatchfilesReloader provides the following advantages:
Much lower CPU usage
Django’s default StatReloader works by polling all files for changes, sleeping for one second, and looping. Meanwhile, WatchfilesReloader avoids polling; instead, it asks the operating system to report any changes to the watched files.
The difference can be stark and save you significant battery when developing on a device that isn’t connected to a power source. A quick benchmark on a medium-sized project (385,000 lines plus 206 installed packages) using an M1 MacBook showed StatReloader using ~10% of a CPU every other second, while WatchfilesReloader uses 0%.
Reduced reload time
StatReloader can take one second or more to detect changes, while WatchfilesReloader can take as little as 50 milliseconds. This means that runserver starts reloading your code more quickly, and you can iterate more rapidly.
Batched reloads
Sometimes multiple file changes can occur in quick succession, such as when one file is saved and then updated by a formatter, or when multiple files are changed when you git switch to another branch. In such cases, StatReloader can trigger multiple reloads, unnecessarily slowing down progress, or it can miss some changes, leading to old code being left running. WatchfilesReloader instead batches changes, using watchfiles’ debounce feature, so that multiple changes will only trigger a single reload.
WatchfilesReloader uses watchfiles’ defaults here, waiting for changes within a 50 millisecond window, and repeating this wait for up to 1600 milliseconds, as long as changes keep occurring. These values provide a good balance between responsiveness and batching.
On some platforms (Windows Subsystem for Linux, or WSL), watchfiles will fall back to a polling approach. This is still more efficient than StatReloader though, because it’s implemented in Rust.
watchfiles has some configuration options which can be configured through environment variables. See the watchfiles documentation for details.
History
Django’s runserver started with only the logic for StatReloader, because it’s simple and works on all platforms.
In Django 1.7 (2014), Django gained support for using the Linux file-watching API inotify, through the pyinotify package. This provided efficient reloading, but was limited to Linux. This was thanks to Unai Zalakain, Chris Lamb, and Pascal Hartig for that work in Ticket #9722.
In Django 2.2 (2019), Django gained support for Watchman, a cross-platform file-watching service from Facebook, via the pywatchman package. This provides efficient reloading on Linux and macOS, but requires developers to install and run the Watchman service separately. Thanks to Tom Forbes for that work in Ticket #27685.
Unfortunately, the pywatchman package stopped working on Python 3.10, as reported in its Issue #970 (2021). This issue remained unfixed for a long time, until March 2024, after the release of Python 3.12. It appears that Watchman and pywatchman are not a priority for maintenance by Facebook.
In 2022, Samel Colvin released watchfiles, a new cross-platform file-watching library for Python. It is powered by Notify, a popular and established Rust crate. (watchfiles is also the Rust-powered rebuild of Samuel’s earlier watchgod package (2017).)
I created django-watchfiles in 2022 to integrate watchfiles with Django’s autoreloader. The inspiration came from writing about using Watchman in Boost Your Django DX and feeling a bit dismayed that it wasn’t particularly easy, and that it wasn’t (yet) working on Python 3.10.
django-watchfiles had its first stable release in 2024. I may propose integrating it with Django core at some point, when it’s more established.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_watchfiles-1.4.0.tar.gz.
File metadata
- Download URL: django_watchfiles-1.4.0.tar.gz
- Upload date:
- Size: 8.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
88e253e8e8427834eac467923d334c35010279b3e9ceb5bb91014be83975b11b
|
|
| MD5 |
cde1611ea31d2813cf4458a7b7097987
|
|
| BLAKE2b-256 |
1a8951b82766a1c937dea9fb92f0fb7666919d120379fc26dc84ab504e35f37e
|
Provenance
The following attestation bundles were made for django_watchfiles-1.4.0.tar.gz:
Publisher:
main.yml on adamchainz/django-watchfiles
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_watchfiles-1.4.0.tar.gz -
Subject digest:
88e253e8e8427834eac467923d334c35010279b3e9ceb5bb91014be83975b11b - Sigstore transparency entry: 546572484
- Sigstore integration time:
-
Permalink:
adamchainz/django-watchfiles@911ea4836b5742e4861e6642cf43337564c4f6bb -
Branch / Tag:
refs/tags/1.4.0 - Owner: https://github.com/adamchainz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@911ea4836b5742e4861e6642cf43337564c4f6bb -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_watchfiles-1.4.0-py3-none-any.whl.
File metadata
- Download URL: django_watchfiles-1.4.0-py3-none-any.whl
- Upload date:
- Size: 6.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40cb3180987c63629b0681ab228b65afd68e0f783388cc72a45620378213bb48
|
|
| MD5 |
1648bf521b3825847a56ef8c4b3c224c
|
|
| BLAKE2b-256 |
c7853d31f347e1a3eef9be381792df1994ff25e4db4659ab40a5cc3f814e3a1a
|
Provenance
The following attestation bundles were made for django_watchfiles-1.4.0-py3-none-any.whl:
Publisher:
main.yml on adamchainz/django-watchfiles
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_watchfiles-1.4.0-py3-none-any.whl -
Subject digest:
40cb3180987c63629b0681ab228b65afd68e0f783388cc72a45620378213bb48 - Sigstore transparency entry: 546572502
- Sigstore integration time:
-
Permalink:
adamchainz/django-watchfiles@911ea4836b5742e4861e6642cf43337564c4f6bb -
Branch / Tag:
refs/tags/1.4.0 - Owner: https://github.com/adamchainz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
main.yml@911ea4836b5742e4861e6642cf43337564c4f6bb -
Trigger Event:
push
-
Statement type: