2024-11-19 13:52:12 -06:00
# Creating projects
uv supports creating a project with `uv init` .
2024-11-20 08:50:14 -06:00
When creating projects, uv supports two basic templates: [**applications** ](#applications ) and
[**libraries** ](#libraries ). By default, uv will create a project for an application. The `--lib`
flag can be used to create a project for a library instead.
## Target directory
2024-11-19 13:52:12 -06:00
uv will create a project in the working directory, or, in a target directory by providing a name,
2025-11-10 16:33:08 -07:00
e.g., `uv init foo` . The working directory can be modified with the `--directory` option, which will
cause the target directory path will be interpreted relative to the specified working directory. If
there's already a project in the target directory, i.e., if there's a `pyproject.toml` , uv will exit
with an error.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
## Applications
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
Application projects are suitable for web servers, scripts, and command-line interfaces.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
Applications are the default target for `uv init` , but can also be specified with the `--app` flag.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
``` console
$ uv init example-app
```
2024-11-19 13:52:12 -06:00
2025-02-13 16:58:02 -05:00
The project includes a `pyproject.toml` , a sample file (`main.py` ), a readme, and a Python version
2024-11-20 08:50:14 -06:00
pin file (`.python-version` ).
2024-11-19 13:52:12 -06:00
``` console
$ tree example-app
example-app
├── .python-version
├── README.md
2025-02-13 16:58:02 -05:00
├── main.py
2024-11-19 13:52:12 -06:00
└── pyproject.toml
```
2025-02-14 16:59:25 -05:00
!!! note
Prior to v0.6.0, uv created a file named `hello.py` instead of `main.py` .
2024-11-20 08:50:14 -06:00
The `pyproject.toml` includes basic metadata. It does not include a build system, it is not a
[package ](./config.md#project-packaging ) and will not be installed into the environment:
2024-11-19 13:52:12 -06:00
```toml title="pyproject.toml"
[project]
name = "example-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
` ``
2024-11-20 08:50:14 -06:00
The sample file defines a ` main` function with some standard boilerplate:
2024-11-19 13:52:12 -06:00
2025-02-13 16:58:02 -05:00
` ``python title="main.py"
2024-11-19 13:52:12 -06:00
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
` ``
2024-11-20 08:50:14 -06:00
Python files can be executed with ` uv run`:
2024-11-19 13:52:12 -06:00
` ``console
2025-03-19 01:20:03 +05:30
$ cd example-app
2025-02-13 16:58:02 -05:00
$ uv run main.py
2024-11-19 13:52:12 -06:00
Hello from example-project!
` ``
2024-11-20 08:50:14 -06:00
## Packaged applications
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
Many use-cases require a [package](./config.md#project-packaging). For example, if you are creating
a command-line interface that will be published to PyPI or if you want to define tests in a
dedicated directory.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
The ` --package` flag can be used to create a packaged application:
2024-11-19 13:52:12 -06:00
` ``console
2024-11-20 08:50:14 -06:00
$ uv init --package example-pkg
` ``
The source code is moved into a ` src` directory with a module directory and an ` __init__.py` file:
` ``console
$ tree example-pkg
example-pkg
2024-11-19 13:52:12 -06:00
├── .python-version
├── README.md
├── pyproject.toml
└── src
2025-03-19 01:20:03 +05:30
└── example_pkg
2024-11-19 13:52:12 -06:00
└── __init__.py
` ``
2024-11-20 08:50:14 -06:00
A [build system](./config.md#build-systems) is defined, so the project will be installed into the
environment:
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
` ``toml title="pyproject.toml" hl_lines="12-14"
2024-11-19 13:52:12 -06:00
[project]
2024-11-20 08:50:14 -06:00
name = "example-pkg"
2024-11-19 13:52:12 -06:00
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
2024-11-20 08:50:14 -06:00
[project.scripts]
2025-03-19 01:20:03 +05:30
example-pkg = "example_pkg:main"
2024-11-20 08:50:14 -06:00
2024-11-19 13:52:12 -06:00
[build-system]
2025-12-02 17:48:28 -06:00
requires = ["uv_build>=0.9.15,<0.10.0"]
2025-07-30 14:04:07 +02:00
build-backend = "uv_build"
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
!!! tip
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
The ` --build-backend` option can be used to request an alternative build system.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
A [command](./config.md#entry-points) definition is included:
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
` ``toml title="pyproject.toml" hl_lines="9 10"
[project]
name = "example-pkg"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
[project.scripts]
2025-03-19 01:20:03 +05:30
example-pkg = "example_pkg:main"
2024-11-20 08:50:14 -06:00
[build-system]
2025-12-02 17:48:28 -06:00
requires = ["uv_build>=0.9.15,<0.10.0"]
2025-07-30 14:04:07 +02:00
build-backend = "uv_build"
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
The command can be executed with ` uv run`:
2024-11-19 13:52:12 -06:00
` ``console
2025-03-19 01:20:03 +05:30
$ cd example-pkg
$ uv run example-pkg
2024-11-20 08:50:14 -06:00
Hello from example-pkg!
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
## Libraries
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
A library provides functions and objects for other projects to consume. Libraries are intended to be
built and distributed, e.g., by uploading them to PyPI.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
Libraries can be created by using the ` --lib` flag:
2024-11-19 13:52:12 -06:00
` ``console
2024-11-20 08:50:14 -06:00
$ uv init --lib example-lib
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
!!! note
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
Using ` --lib` implies ` --package`. Libraries always require a packaged project.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
As with a [packaged application](#packaged-applications), a ` src` layout is used. A ` py.typed`
marker is included to indicate to consumers that types can be read from the library:
2024-11-19 13:52:12 -06:00
` ``console
2024-11-20 08:50:14 -06:00
$ tree example-lib
example-lib
2024-11-19 13:52:12 -06:00
├── .python-version
├── README.md
├── pyproject.toml
└── src
2024-11-20 08:50:14 -06:00
└── example_lib
├── py.typed
2024-11-19 13:52:12 -06:00
└── __init__.py
` ``
2024-11-20 08:50:14 -06:00
!!! note
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
A ` src` layout is particularly valuable when developing libraries. It ensures that the library is
isolated from any ` python` invocations in the project root and that distributed library code is
well separated from the rest of the project source.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
A [build system](./config.md#build-systems) is defined, so the project will be installed into the
environment:
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
` ``toml title="pyproject.toml" hl_lines="12-14"
2024-11-19 13:52:12 -06:00
[project]
2024-11-20 08:50:14 -06:00
name = "example-lib"
2024-11-19 13:52:12 -06:00
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[build-system]
2025-12-02 17:48:28 -06:00
requires = ["uv_build>=0.9.15,<0.10.0"]
2025-07-30 14:04:07 +02:00
build-backend = "uv_build"
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
!!! tip
You can select a different build backend template by using ` --build-backend` with ` hatchling`,
2025-05-05 15:52:31 +02:00
` uv_build`, ` flit-core`, ` pdm-backend`, ` setuptools`, ` maturin`, or ` scikit-build-core`. An
alternative backend is required if you want to create a [library with extension modules](#projects-with-extension-modules).
2024-11-20 08:50:14 -06:00
The created module defines a simple API function:
` ``python title="__init__.py"
def hello() -> str:
return "Hello from example-lib!"
` ``
And you can import and execute it using ` uv run`:
2024-11-19 13:52:12 -06:00
` ``console
2025-03-19 01:20:03 +05:30
$ cd example-lib
$ uv run python -c "import example_lib; print(example_lib.hello())"
2024-11-20 08:50:14 -06:00
Hello from example-lib!
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
## Projects with extension modules
Most Python projects are "pure Python", meaning they do not define modules in other languages like
C, C++, FORTRAN, or Rust. However, projects with extension modules are often used for performance
sensitive code.
2024-11-21 08:24:21 -06:00
Creating a project with an extension module requires choosing an alternative build system. uv
supports creating projects with the following build systems that support building extension modules:
2024-11-20 08:50:14 -06:00
- [` maturin`](https://www.maturin.rs) for projects with Rust
2024-11-21 08:42:47 -06:00
- [` scikit-build-core`](https://github.com/scikit-build/scikit-build-core) for projects with C, C++,
2024-11-20 08:50:14 -06:00
FORTRAN, Cython
2024-11-21 08:24:21 -06:00
Specify the build system with the ` --build-backend` flag:
2024-11-20 08:50:14 -06:00
` ``console
$ uv init --build-backend maturin example-ext
` ``
!!! note
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
Using ` --build-backend` implies ` --package`.
2024-11-19 13:52:12 -06:00
2024-11-20 08:50:14 -06:00
The project contains a ` Cargo.toml` and a ` lib.rs` file in addition to the typical Python project
files:
2024-11-19 13:52:12 -06:00
` ``console
2024-11-20 08:50:14 -06:00
$ tree example-ext
example-ext
2024-11-19 13:52:12 -06:00
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
2024-11-20 08:50:14 -06:00
└── example_ext
2024-11-19 13:52:12 -06:00
├── __init__.py
└── _core.pyi
` ``
2024-11-21 08:24:21 -06:00
!!! note
2024-11-21 08:42:47 -06:00
If using ` scikit-build-core`, you'll see CMake configuration and a ` main.cpp` file instead.
2024-11-21 08:24:21 -06:00
2024-11-20 08:50:14 -06:00
The Rust library defines a simple function:
` ``rust title="src/lib.rs"
use pyo3::prelude::*;
#[pymodule]
2025-10-27 11:35:39 +01:00
mod _core {
use pyo3::prelude::*;
#[pyfunction]
fn hello_from_bin() -> String {
"Hello from example-ext!".to_string()
}
2024-11-20 08:50:14 -06:00
}
` ``
And the Python module imports it:
` ``python title="src/example_ext/__init__.py"
from example_ext._core import hello_from_bin
2025-01-07 18:07:44 +01:00
2024-11-20 08:50:14 -06:00
def main() -> None:
print(hello_from_bin())
` ``
The command can be executed with ` uv run`:
2024-11-19 13:52:12 -06:00
` ``console
2025-03-19 01:20:03 +05:30
$ cd example-ext
$ uv run example-ext
2024-11-20 08:50:14 -06:00
Hello from example-ext!
2024-11-19 13:52:12 -06:00
` ``
2024-11-20 08:50:14 -06:00
!!! important
2025-09-14 16:20:17 +02:00
When creating a project with maturin or scikit-build-core, uv configures [` tool.uv.cache-keys`](https://docs.astral.sh/uv/reference/settings/#cache-keys)
to include common source file types. To force a rebuild, e.g. when changing files outside
` cache-keys` or when not using ` cache-keys`, use ` --reinstall`.
2025-02-05 10:12:27 -06:00
## Creating a minimal project
If you only want to create a ` pyproject.toml`, use the ` --bare` option:
` ``console
$ uv init example --bare
` ``
uv will skip creating a Python version pin file, a README, and any source directories or files.
Additionally, uv will not initialize a version control system (i.e., ` git`).
` ``console
$ tree example-bare
example-bare
└── pyproject.toml
` ``
uv will also not add extra metadata to the ` pyproject.toml`, such as the ` description` or ` authors`.
` ``toml
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
` ``
The ` --bare` option can be used with other options like ` --lib` or ` --build-backend` — in these
cases uv will still configure a build system but will not create the expected file structure.
When ` --bare` is used, additional features can still be used opt-in:
` ``console
2025-02-05 17:21:58 -06:00
$ uv init example --bare --description "Hello world" --author-from git --vcs git --python-pin
2025-02-05 10:12:27 -06:00
` ``