uv/docs/concepts/projects/init.md
Jatinderjit Singh a95f4cf553
Some checks are pending
CI / mkdocs (push) Waiting to run
CI / cargo dev generate-all (push) Blocked by required conditions
CI / cargo shear (push) Waiting to run
CI / cargo test | ubuntu (push) Blocked by required conditions
CI / Determine changes (push) Waiting to run
CI / lint (push) Waiting to run
CI / cargo clippy | ubuntu (push) Blocked by required conditions
CI / cargo clippy | windows (push) Blocked by required conditions
CI / cargo test | macos (push) Blocked by required conditions
CI / cargo test | windows (push) Blocked by required conditions
CI / check windows trampoline | aarch64 (push) Blocked by required conditions
CI / check windows trampoline | i686 (push) Blocked by required conditions
CI / build binary | windows aarch64 (push) Blocked by required conditions
CI / check windows trampoline | x86_64 (push) Blocked by required conditions
CI / test windows trampoline | i686 (push) Blocked by required conditions
CI / test windows trampoline | x86_64 (push) Blocked by required conditions
CI / typos (push) Waiting to run
CI / check system | pypy on ubuntu (push) Blocked by required conditions
CI / build binary | linux libc (push) Blocked by required conditions
CI / build binary | linux musl (push) Blocked by required conditions
CI / build binary | macos aarch64 (push) Blocked by required conditions
CI / build binary | macos x86_64 (push) Blocked by required conditions
CI / build binary | windows x86_64 (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / build binary | freebsd (push) Blocked by required conditions
CI / ecosystem test | pydantic/pydantic-core (push) Blocked by required conditions
CI / ecosystem test | prefecthq/prefect (push) Blocked by required conditions
CI / smoke test | windows aarch64 (push) Blocked by required conditions
CI / ecosystem test | pallets/flask (push) Blocked by required conditions
CI / smoke test | linux (push) Blocked by required conditions
CI / check system | alpine (push) Blocked by required conditions
CI / smoke test | macos (push) Blocked by required conditions
CI / smoke test | windows x86_64 (push) Blocked by required conditions
CI / integration test | conda on ubuntu (push) Blocked by required conditions
CI / integration test | deadsnakes python3.9 on ubuntu (push) Blocked by required conditions
CI / integration test | free-threaded on linux (push) Blocked by required conditions
CI / integration test | free-threaded on windows (push) Blocked by required conditions
CI / integration test | pypy on ubuntu (push) Blocked by required conditions
CI / integration test | pypy on windows (push) Blocked by required conditions
CI / integration test | graalpy on ubuntu (push) Blocked by required conditions
CI / integration test | graalpy on windows (push) Blocked by required conditions
CI / integration test | github actions (push) Blocked by required conditions
CI / integration test | determine publish changes (push) Blocked by required conditions
CI / integration test | uv publish (push) Blocked by required conditions
CI / integration test | uv_build (push) Blocked by required conditions
CI / check cache | ubuntu (push) Blocked by required conditions
CI / check cache | macos aarch64 (push) Blocked by required conditions
CI / check system | python on debian (push) Blocked by required conditions
CI / check system | python on fedora (push) Blocked by required conditions
CI / check system | python on ubuntu (push) Blocked by required conditions
CI / check system | python on opensuse (push) Blocked by required conditions
CI / check system | python on rocky linux 8 (push) Blocked by required conditions
CI / check system | python on rocky linux 9 (push) Blocked by required conditions
CI / check system | pyston (push) Blocked by required conditions
CI / check system | python on macos aarch64 (push) Blocked by required conditions
CI / check system | homebrew python on macos aarch64 (push) Blocked by required conditions
CI / check system | python on macos x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86-64 (push) Blocked by required conditions
CI / check system | python3.10 on windows x86 (push) Blocked by required conditions
CI / check system | python3.13 on windows x86-64 (push) Blocked by required conditions
CI / check system | x86-64 python3.13 on windows aarch64 (push) Blocked by required conditions
CI / check system | windows registry (push) Blocked by required conditions
CI / check system | python3.12 via chocolatey (push) Blocked by required conditions
CI / check system | conda3.8 on linux x86-64 (push) Blocked by required conditions
CI / check system | python3.9 via pyenv (push) Blocked by required conditions
CI / check system | python3.13 (push) Blocked by required conditions
CI / check system | conda3.11 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.8 on macos aarch64 (push) Blocked by required conditions
CI / check system | conda3.11 on linux x86-64 (push) Blocked by required conditions
CI / check system | conda3.11 on windows x86-64 (push) Blocked by required conditions
CI / check system | conda3.8 on windows x86-64 (push) Blocked by required conditions
CI / check system | amazonlinux (push) Blocked by required conditions
CI / check system | embedded python3.10 on windows x86-64 (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions
Fix --directory path in examples (#12165)
<!--
Thank you for contributing to uv! To help us out with reviewing, please
consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->
The examples assume that the packages are in the project root directory.
However, they are nested inside `src`, and the commands in the examples
do not work as intended.

I could not find any related issues.

## Test Plan

<!-- How was it tested? -->

I tested it by executing the commands on my terminal - Linux and Windows
(PowerShell).

---------

Co-authored-by: Charlie Marsh <charlie.r.marsh@gmail.com>
2025-03-18 15:50:03 -04:00

341 lines
8.5 KiB
Markdown

# Creating projects
uv supports creating a project with `uv init`.
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
uv will create a project in the working directory, or, in a target directory by providing a name,
e.g., `uv init foo`. If there's already a project in the target directory, i.e., if there's a
`pyproject.toml`, uv will exit with an error.
## Applications
Application projects are suitable for web servers, scripts, and command-line interfaces.
Applications are the default target for `uv init`, but can also be specified with the `--app` flag.
```console
$ uv init example-app
```
The project includes a `pyproject.toml`, a sample file (`main.py`), a readme, and a Python version
pin file (`.python-version`).
```console
$ tree example-app
example-app
├── .python-version
├── README.md
├── main.py
└── pyproject.toml
```
!!! note
Prior to v0.6.0, uv created a file named `hello.py` instead of `main.py`.
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:
```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 = []
```
The sample file defines a `main` function with some standard boilerplate:
```python title="main.py"
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
```
Python files can be executed with `uv run`:
```console
$ cd example-app
$ uv run main.py
Hello from example-project!
```
## Packaged applications
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.
The `--package` flag can be used to create a packaged application:
```console
$ 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
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_pkg
└── __init__.py
```
A [build system](./config.md#build-systems) is defined, so the project will be installed into the
environment:
```toml title="pyproject.toml" hl_lines="12-14"
[project]
name = "example-pkg"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[project.scripts]
example-pkg = "example_pkg:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
!!! tip
The `--build-backend` option can be used to request an alternative build system.
A [command](./config.md#entry-points) definition is included:
```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 = []
[project.scripts]
example-pkg = "example_pkg:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
The command can be executed with `uv run`:
```console
$ cd example-pkg
$ uv run example-pkg
Hello from example-pkg!
```
## Libraries
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.
Libraries can be created by using the `--lib` flag:
```console
$ uv init --lib example-lib
```
!!! note
Using `--lib` implies `--package`. Libraries always require a packaged project.
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:
```console
$ tree example-lib
example-lib
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_lib
├── py.typed
└── __init__.py
```
!!! note
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.
A [build system](./config.md#build-systems) is defined, so the project will be installed into the
environment:
```toml title="pyproject.toml" hl_lines="12-14"
[project]
name = "example-lib"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
!!! tip
You can select a different build backend template by using `--build-backend` with `hatchling`,
`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).
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`:
```console
$ cd example-lib
$ uv run python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
```
## 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.
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:
- [`maturin`](https://www.maturin.rs) for projects with Rust
- [`scikit-build-core`](https://github.com/scikit-build/scikit-build-core) for projects with C, C++,
FORTRAN, Cython
Specify the build system with the `--build-backend` flag:
```console
$ uv init --build-backend maturin example-ext
```
!!! note
Using `--build-backend` implies `--package`.
The project contains a `Cargo.toml` and a `lib.rs` file in addition to the typical Python project
files:
```console
$ tree example-ext
example-ext
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
└── example_ext
├── __init__.py
└── _core.pyi
```
!!! note
If using `scikit-build-core`, you'll see CMake configuration and a `main.cpp` file instead.
The Rust library defines a simple function:
```rust title="src/lib.rs"
use pyo3::prelude::*;
#[pyfunction]
fn hello_from_bin() -> String {
"Hello from example-ext!".to_string()
}
#[pymodule]
fn _core(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(hello_from_bin, m)?)?;
Ok(())
}
```
And the Python module imports it:
```python title="src/example_ext/__init__.py"
from example_ext._core import hello_from_bin
def main() -> None:
print(hello_from_bin())
```
The command can be executed with `uv run`:
```console
$ cd example-ext
$ uv run example-ext
Hello from example-ext!
```
!!! important
Changes to the extension code in `lib.rs` or `main.cpp` will require running `--reinstall` to
rebuild them.
## 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
$ uv init example --bare --description "Hello world" --author-from git --vcs git --python-pin
```