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 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.scriptsinstead of attachedscriptsfoldersthe benefits of
srclayout with a common, documented and well understood structure.
myapp/pyproject.tomlThe
pyproject.tomlfile contains ascriptsentry pointmyapp:main:myapp/pyproject.toml¶] requires-python = ">=3.13"
myapp/src/myapp/__init__.pyThe 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 . Resolved 1 package in 1ms Audited in 0.01ms $ uv run python >>> import myapp >>> myapp.main() Hello from myapp!
uv.lockfileWith
uv add .theuv.lockfile was also created alongside thepyproject.tomlfile.uv.lockis 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.lockcontains 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.lockis a human-readable TOML file, but is managed byuvand should not be edited manually.Note
If
uvis 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.TXTfile created can then be used withuv pip installor 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'",
]