Python
How Anvil runs Django, FastAPI and Flask projects through uv, installs Python versions and picks one per project.
What Anvil detects
| Type | Detected by | Started with |
|---|---|---|
| Django | manage.py that imports Django | python manage.py runserver 127.0.0.1:$PORT |
| FastAPI | fastapi in pyproject.toml or requirements.txt | uvicorn <module>:app --host 127.0.0.1 --port $PORT --reload |
| Flask | flask in pyproject.toml or requirements.txt | flask run --host 127.0.0.1 --port $PORT --debug |
With a package.json present, FastAPI and Flask count only if there is also a
main.py, app.py, wsgi.py or app/main.py; otherwise it's a Node.js
application. Python is checked before package.json, so Django with a
frontend stays Django. PHP, Rust, Go and .NET are recognized first; see the
detection table.
FastAPI's module is main (main.py), then app.main (app/main.py), then
app (app.py). Flask finds app.py or wsgi.py itself.
Anvil starts the dev server on a private port passed in $PORT and proxies
<name>.test to it.
Installing Python
Settings › Languages › Python › Install, or:
anvil runtime install python 3.13Versions: 3.14, 3.13, 3.12, 3.11. The first install downloads a pinned
uv release, checked against its SHA-256, into
~/.anvil/runtimes/uv. uv then installs the python-build-standalone build
(checked against uv's built-in checksums) into ~/.anvil/runtimes/python.
Neither Anvil nor uv installs a Python by itself (uv runs with downloads set
to manual), and uv uses only Pythons in ~/.anvil, never the system's.
Choosing the version
There is no default version.
- Without a pin, uv chooses among Anvil's Pythons: the version
.python-versionnames, else the newestrequires-pythonallows, else the newest installed.requirements.txt-only projects still follow.python-version. If the requested version isn't installed, uv stops and the application's log shows e.g.No interpreter found for Python 3.11 in managed installations; install it in Settings › Languages › Python and start again. A.python-versionthatrequires-pythonrules out also stops uv. - With a pin (
anvil app runtime mysite 3.12, or Python version in the Settings tab), Anvil passes it asUV_PYTHON, overriding.python-version. Outsiderequires-python, uv stops with an error in the log.anvil app runtime mysitegoes back to automatic.
Without a pin, the Overview and the Automatic entry show the
.python-version version if installed, else the newest. Anvil doesn't read
requires-python, so what uv runs can differ.
Running an application
The start command runs through uv run, which installs dependencies first:
| The project has | Command |
|---|---|
pyproject.toml with a [project] table | uv run <command> |
requirements.txt | uv run --no-project --with-requirements requirements.txt <command> |
| neither | uv run --no-project --with <framework> <command> |
FastAPI adds --with uvicorn. A pyproject.toml without a [project] table
(only ruff, poetry, etc. settings) doesn't count as a uv project.
Start command and port: Start command and Port in Settings, or
anvil app command / anvil app port (no value resets). The automatic port
is derived from the name, in 41000–44999, moving up on collision. The dev
server gets PORT, and HOST/HOSTNAME = 127.0.0.1.
The dev server doesn't start on its own: Start in the Dev tab, or
anvil app start mysite while the desktop app is open (this also starts dev
processes marked Dev start). To start it with Anvil, turn on Start with
Anvil in Settings or run anvil app autostart mysite true (off by default;
with the CLI alone, restart anvil start). It runs until stopped or Anvil
quits; while stopped, <name>.test shows a "not running" page.
Django settings
The Overview shows the lines to add to settings.py once:
if DEBUG: # Anvil
ALLOWED_HOSTS += [".test", "localhost", "127.0.0.1"]
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")Without them Django returns 400 for .test addresses and forms fail CSRF.
.localhost passes the host check in debug, but forms still need the proxy
line. Both apply only under DEBUG.
In your terminal
No python, pip or uv terminal command, and uv adds no Python links to a
bin folder. Anvil's uv is ~/.anvil/runtimes/uv/uv; run it with the
variables in Caches and files to use Anvil's Pythons and
caches.
Caches and files
| Variable | Value |
|---|---|
UV_PYTHON_INSTALL_DIR | ~/.anvil/runtimes/python |
UV_CACHE_DIR | ~/.anvil/cache/uv |
UV_PYTHON_CACHE_DIR | ~/.anvil/cache/uv-python |
UV_TOOL_DIR, UV_TOOL_BIN_DIR | ~/.anvil/cache/uv-tools, ~/.anvil/cache/uv-tools/bin |
UV_PROJECT_ENVIRONMENT | ~/.anvil/cache/uv-venvs/<name> |
UV_MANAGED_PYTHON | 1 |
UV_PYTHON_DOWNLOADS | manual |
UV_PYTHON_BIN_DIR | ~/.anvil/cache/uv-python-bin |
UV_PYTHON_INSTALL_BIN | 0 |
UV_PYTHON | The pinned version, only when the application has a pin |
An existing .venv is left alone. A pyproject.toml project gets a uv.lock;
a requirements.txt-only project gets nothing added.
New applications
anvil new django site
anvil new fastapi api
anvil new flask webOr New… (⌘N) in the app, under Python. Needs a Python installed.
| Template | What it creates |
|---|---|
django | django-admin startproject with the settings package named config, the lines above appended to config/settings.py (with the domain suffix you use), and a requirements.txt with django |
fastapi | main.py with an app and a requirements.txt with fastapi and uvicorn |
flask | app.py with an app and a requirements.txt with flask |
All templates take --git/--no-git and --https/--no-https; see
New applications.
Differences from production
- The framework's dev server runs: Django's
runserver, uvicorn with--reload, Flask with--debug, on 127.0.0.1 only. - The environment is in
~/.anvil/cache/uv-venvs, not in the project. - Only Pythons installed through Anvil run, never the system's.
Removing a version
Hover the version in Settings › Languages › Python and click
Uninstall, or anvil runtime uninstall python 3.12. uv removes it from
~/.anvil/runtimes/python.
Anvil refuses while applications are pinned to it ("api uses Python 3.12 —
switch it to another version first"); Settings then shows Pinned by with
their names instead of Uninstall. Unpin: set Python version to
Automatic or another version, or run anvil app runtime api without a
version (with only one version installed the field is disabled; use the
command). A version only .python-version or requires-python asks for isn't
a pin: the uninstall goes ahead, and the application fails to start with uv's
error until it's reinstalled.