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
myapp/pyproject.toml

The pyproject.toml file contains a scripts entry point myapp: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!

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 attached scripts folders

  • the benefits of src layout with a common, documented and well understood structure.

uv.lock file

With uv add --dev . the uv.lock file was also created alongside the pyproject.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 by uv 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 using uv export --format requirements-txt > CONSTRAINTS.TXT. Conversely, the CONSTRAINTS.TXT file created can then be used with uv pip install or other tools.

Aktualisieren von uv.lock

uv.lock is updated regularly when uv sync and uv run are called.

--frozen

leaves the uv.lock file unchanged.

--no-sync

avoids updating the environment during uv run calls.

--locked

ensures that the lock file matches the project metadata. If the lockfile is not up-to-date, an error message is issued instead of updating the lockfile.

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.

uv lock --upgrade

updates all packages.

uv lock --upgrade-package PACKAGE==VERSION

upgrades a single package to a specific version.

You can also use the pre-commit framework to regularly update your uv.lock file:

.pre-commit-config.yaml
- repo: https://github.com/astral-sh/uv-pre-commit
  rev: 0.4.24
  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 in compliance with PEP 508, for example to restrict the uv.lock file to macOS and Linux only:

[tool.uv]
environments = [
    "sys_platform == 'darwin'",
    "sys_platform == 'linux'",
]