# uvicorn-hmr
[](https://pypi.org/project/uvicorn-hmr/)
[](https://pepy.tech/projects/uvicorn-hmr)
This package provides hot module reloading (HMR) for [`uvicorn`](https://github.com/encode/uvicorn).
It uses [`watchfiles`](https://github.com/samuelcolvin/watchfiles) to detect FS modifications,
re-executes the corresponding modules with [`hmr`](https://github.com/promplate/pyth-on-line/tree/main/packages/hmr) and restart the server (in the same process).
**HOT** means the main process never restarts, and reloads are fine-grained (only the changed modules and their dependent modules are reloaded).
Since the reload is on-demand and the server is not restarted on every save, it is much faster than the built-in `--reload` option provided by `uvicorn`.
## Why?
1. When you use `uvicorn --reload`, it restarts the whole process on every file change, but restarting the whole process is unnecessary:
- There is no need to restart the Python interpreter, neither all the 3rd-party packages you imported.
- Your changes usually affect only one single file, the rest of your application remains unchanged.
2. `hmr` tracks dependencies at runtime, remembers the relationships between your modules and only reruns necessary modules.
3. So you can save a lot of time by not restarting the whole process on every file change. You can see a significant speedup for debugging large applications.
4. Although magic is involved, we thought and tested them very carefully, so everything works just as-wished.
- Your lazy loading through module-level `__getattr__` still works
- Your runtime imports through `importlib.import_module` or even `__import__` still work
- Even valid circular imports between `__init__.py` and sibling modules still work
- Fine-grained dependency tracking in the above cases still work
- Decorators still work, even meta programming hacks like `getsource` calls work too
- Standard dunder metadata like `__name__`, `__doc__`, `__file__`, `__package__` are correctly set
- ASGI lifecycles are preserved
Normally, you can replace `uvicorn --reload` with `uvicorn-hmr` and everything will work as expected, with a much faster reload experience.
## Installation
```sh
pip install uvicorn-hmr
```
<details>
<summary> Or with extra dependencies: </summary>
```sh
pip install uvicorn-hmr[all]
```
This will install `fastapi-reloader` too, which enables you to use `--reload` flag to reload the browser pages when the server restarts.
> When you enable the `--reload` flag, it means you want to use the `fastapi-reloader` package to enable automatic HTML page reloading.
> This behavior differs from Uvicorn's built-in `--reload` functionality. (See the configuration section for more details.)
>
> Server reloading is a core feature of `uvicorn-hmr` and is always active, regardless of whether the `--reload` flag is set.
> The `--reload` flag specifically controls auto-reloading of HTML pages, a feature not available in Uvicorn.
>
> If you don't need HTML page auto-reloading, simply omit the `--reload` flag.
> If you do want this feature, ensure that `fastapi-reloader` is installed by running: `pip install fastapi-reloader` or `pip install uvicorn-hmr[all]`.
</details>
## Usage
Replace
```sh
uvicorn main:app --reload
```
with
```sh
uvicorn-hmr main:app
```
Everything will work as-expected, but with **hot** module reloading.
## Configuration
I haven't copied all the configurable options from `uvicorn`. But contributions are welcome!
For now, `host`, `port`, `log-level`, `reload_include`, `reload_exclude`, `env-file` are supported and have exactly the same semantics and types as in `uvicorn`.
The following options are supported but do not have any alternative in `uvicorn`:
- `--reload`: Enables auto-refreshing of HTML pages in the browser whenever the server restarts. Useful for demo purposes and visual debugging. This is **totally different** from `uvicorn`'s built-in `--reload` option, which is always enabled and can't be disabled in `uvicorn-hmr` because hot-reloading is the core feature of this package.
- `--clear`: Wipes the terminal before each reload. Just like `vite` does by default.
The two features above are opinionated and are disabled by default. They are just my personal practices. If you find them useful or want to suggest some other features, feel free to open an issue.
Raw data
{
"_id": null,
"home_page": null,
"name": "uvicorn-hmr",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.12",
"maintainer_email": null,
"keywords": "uvicorn, hot-reload, hmr, reload, server",
"author": null,
"author_email": "Muspi Merol <me@promplate.dev>",
"download_url": "https://files.pythonhosted.org/packages/3a/d6/2f78073b0f33dc3a603da4c7e1eab33c97677e3a56df9eede1a3d8109e5e/uvicorn_hmr-0.0.8.1.tar.gz",
"platform": null,
"description": "# uvicorn-hmr\n\n[](https://pypi.org/project/uvicorn-hmr/)\n[](https://pepy.tech/projects/uvicorn-hmr)\n\nThis package provides hot module reloading (HMR) for [`uvicorn`](https://github.com/encode/uvicorn).\n\nIt uses [`watchfiles`](https://github.com/samuelcolvin/watchfiles) to detect FS modifications,\nre-executes the corresponding modules with [`hmr`](https://github.com/promplate/pyth-on-line/tree/main/packages/hmr) and restart the server (in the same process).\n\n**HOT** means the main process never restarts, and reloads are fine-grained (only the changed modules and their dependent modules are reloaded).\nSince the reload is on-demand and the server is not restarted on every save, it is much faster than the built-in `--reload` option provided by `uvicorn`.\n\n## Why?\n\n1. When you use `uvicorn --reload`, it restarts the whole process on every file change, but restarting the whole process is unnecessary:\n - There is no need to restart the Python interpreter, neither all the 3rd-party packages you imported.\n - Your changes usually affect only one single file, the rest of your application remains unchanged.\n2. `hmr` tracks dependencies at runtime, remembers the relationships between your modules and only reruns necessary modules.\n3. So you can save a lot of time by not restarting the whole process on every file change. You can see a significant speedup for debugging large applications.\n4. Although magic is involved, we thought and tested them very carefully, so everything works just as-wished.\n - Your lazy loading through module-level `__getattr__` still works\n - Your runtime imports through `importlib.import_module` or even `__import__` still work\n - Even valid circular imports between `__init__.py` and sibling modules still work\n - Fine-grained dependency tracking in the above cases still work\n - Decorators still work, even meta programming hacks like `getsource` calls work too\n - Standard dunder metadata like `__name__`, `__doc__`, `__file__`, `__package__` are correctly set\n - ASGI lifecycles are preserved\n\nNormally, you can replace `uvicorn --reload` with `uvicorn-hmr` and everything will work as expected, with a much faster reload experience.\n\n## Installation\n\n```sh\npip install uvicorn-hmr\n```\n\n<details>\n\n<summary> Or with extra dependencies: </summary>\n\n```sh\npip install uvicorn-hmr[all]\n```\n\nThis will install `fastapi-reloader` too, which enables you to use `--reload` flag to reload the browser pages when the server restarts.\n\n> When you enable the `--reload` flag, it means you want to use the `fastapi-reloader` package to enable automatic HTML page reloading.\n> This behavior differs from Uvicorn's built-in `--reload` functionality. (See the configuration section for more details.)\n>\n> Server reloading is a core feature of `uvicorn-hmr` and is always active, regardless of whether the `--reload` flag is set.\n> The `--reload` flag specifically controls auto-reloading of HTML pages, a feature not available in Uvicorn.\n>\n> If you don't need HTML page auto-reloading, simply omit the `--reload` flag.\n> If you do want this feature, ensure that `fastapi-reloader` is installed by running: `pip install fastapi-reloader` or `pip install uvicorn-hmr[all]`.\n\n</details>\n\n## Usage\n\nReplace\n\n```sh\nuvicorn main:app --reload\n```\n\nwith\n\n```sh\nuvicorn-hmr main:app\n```\n\nEverything will work as-expected, but with **hot** module reloading.\n\n## Configuration\n\nI haven't copied all the configurable options from `uvicorn`. But contributions are welcome!\n\nFor now, `host`, `port`, `log-level`, `reload_include`, `reload_exclude`, `env-file` are supported and have exactly the same semantics and types as in `uvicorn`.\n\nThe following options are supported but do not have any alternative in `uvicorn`:\n\n- `--reload`: Enables auto-refreshing of HTML pages in the browser whenever the server restarts. Useful for demo purposes and visual debugging. This is **totally different** from `uvicorn`'s built-in `--reload` option, which is always enabled and can't be disabled in `uvicorn-hmr` because hot-reloading is the core feature of this package.\n- `--clear`: Wipes the terminal before each reload. Just like `vite` does by default.\n\nThe two features above are opinionated and are disabled by default. They are just my personal practices. If you find them useful or want to suggest some other features, feel free to open an issue.\n",
"bugtrack_url": null,
"license": null,
"summary": "Hot Module Reloading for Uvicorn",
"version": "0.0.8.1",
"project_urls": {
"Homepage": "https://github.com/promplate/hmr"
},
"split_keywords": [
"uvicorn",
" hot-reload",
" hmr",
" reload",
" server"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "2da44e498a2b4f90046a9f463115a54b0da83684d3c90e7ce93cf91bdb0c33a1",
"md5": "dff0f42d52a606e1e466cb3c06322858",
"sha256": "536470996f3c2022d7e81c01df944ec72b327c96bcb97812fdf749748edffe38"
},
"downloads": -1,
"filename": "uvicorn_hmr-0.0.8.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "dff0f42d52a606e1e466cb3c06322858",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.12",
"size": 5637,
"upload_time": "2025-07-12T02:55:32",
"upload_time_iso_8601": "2025-07-12T02:55:32.771863Z",
"url": "https://files.pythonhosted.org/packages/2d/a4/4e498a2b4f90046a9f463115a54b0da83684d3c90e7ce93cf91bdb0c33a1/uvicorn_hmr-0.0.8.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "3ad62f78073b0f33dc3a603da4c7e1eab33c97677e3a56df9eede1a3d8109e5e",
"md5": "06267477eb1c0c9b3bb80304f763764d",
"sha256": "0faa2c183c056a91a916489bdd06d5a057182e8f5f4fe88e318062303c51cb50"
},
"downloads": -1,
"filename": "uvicorn_hmr-0.0.8.1.tar.gz",
"has_sig": false,
"md5_digest": "06267477eb1c0c9b3bb80304f763764d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.12",
"size": 4869,
"upload_time": "2025-07-12T02:55:33",
"upload_time_iso_8601": "2025-07-12T02:55:33.795519Z",
"url": "https://files.pythonhosted.org/packages/3a/d6/2f78073b0f33dc3a603da4c7e1eab33c97677e3a56df9eede1a3d8109e5e/uvicorn_hmr-0.0.8.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-12 02:55:33",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "promplate",
"github_project": "hmr",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "uvicorn-hmr"
}