Apps¶
App projects are suitable for web servers, scripts and CLI. We can also create them with uv init --package
:
$ uv init --package myapp
tree mypack -a
myapp
$ uv init --app myapp
$ tree myapp -a
myapp
├── .git
│ └── ...
├── .gitignore
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── myapp
└── __init__.py
Note
I strongly believe that a Python application should be properly packaged to enjoy the many benefits, such as
source management with importlib
executable scripts with
project.scripts
instead of attachedscripts
foldersthe benefits of
src
layout with a common, documented and well understood structure.
myapp/pyproject.toml
The
pyproject.toml
file contains ascripts
entry pointmyapp:main
:myapp/pyproject.toml¶[project.scripts] myapp = "myapp:main"
myapp/src/myapp/__init__.py
The module defines a CLI function
main()
:myapp/src/myapp/__init__.py¶def main() -> None: print("Hello from myapp!")
It can be called up with
uv run
:$ uv run mypack Hello from myapp!
Alternatively, you can also build a virtual environment and then call
main()
from Python:$ uv add --dev . Resolved 1 package in 1ms Audited in 0.01ms $ uv run python >>> import myapp >>> myapp.main() Hello from myapp!
uv.lock
fileWith
uv add --dev .
theuv.lock
file was also created alongside thepyproject.toml
file.uv.lock
is a cross-platform lock file that records the packages that are to be installed across all possible Python features such as operating system, architecture and Python version.Unlike
pyproject.toml
, which specifies the general requirements of your project,uv.lock
contains the exact resolved versions that are installed in the project environment. This file should be checked into the Git version control system to enable consistent and reproducible installations on different computers.myapp/uv.lock¶version = 1 requires-python = ">=3.13" [[package]] name = "myapp" version = "0.1.0" source = { editable = "." } [package.metadata] [package.metadata.requires-dev] dev = [{ name = "myapp", editable = "." }]
uv.lock
is a human-readable TOML file, but is managed byuv
and should not be edited manually.Note
If
uv
is to be integrated into other tools or workflows, you can export the content to the requirements file format usinguv export --format requirements-txt > CONSTRAINTS.TXT
. Conversely, theCONSTRAINTS.TXT
file created can then be used withuv pip install
or other tools.
Reproducing the Python environment¶
In production environments, you should always use exactly the versions that have
been tested. You can use uv sync --locked
in your environment to ensure that
the uv.lock
file matches the project metadata. Otherwise an error
message will be displayed.
You can then use uv sync --frozen
in the production environment to ensure
that the versions of uv.lock
are used as the source of truth, but if
the uv.lock
file is missing in the production environment, uv sync
--frozen
will terminate with an error. Finally, changes to dependencies in the
pyproject.toml
file are ignored if they are not yet written to the
uv.lock
file.
If you want to use uv run
in a productive environment, the --no-sync
option prevents the environment from being updated.
Updating the Python environment¶
By default, uv
favours the locked versions of the packages when executing
uv sync
and uv lock
. Package versions are only changed if the dependency
conditions of the project exclude the previous, locked version.
With uv lock --upgrade
you can upgrade all packages and with uv lock
--upgrade-package PACKAGE==VERSION
you can upgrade individual packages to a
specific version.
Tip
You can also use the
pre-commit framework to
regularly update your uv.lock
file:
- repo: https://github.com/astral-sh/uv-pre-commit
rev: 0.5.21
hooks:
- id: uv-lock
Restrict platform and Python versions¶
If your project only supports a limited number of platforms or Python versions,
you can do this in the pyprojects.toml
file PEP 508 compliant, for
example to restrict your project to macOS and Linux only you can add the
following section in your pyproject.toml
file:
[tool.uv]
environments = [
"sys_platform == 'darwin'",
"sys_platform == 'linux'",
]