uv/docs/concepts/projects/init.md

241 lines
6.6 KiB
Markdown

# Creating projects
uv supports creating a project with `uv init`.
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., there's a
`pyproject.toml`, uv will exit with an error.
When creating projects, uv distinguishes between two types: [**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.
### 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 --app example-app
$ tree example-app
example-app
├── .python-version
├── README.md
├── hello.py
└── pyproject.toml
```
When creating an application, uv will generate a minimal `pyproject.toml`. A build system is not
defined and the source code is in the top-level directory, e.g., `hello.py`. The project does not
contain a package that will be built and installed into the project 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 created script defines a `main` function with some standard boilerplate:
```python title="hello.py"
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
```
And can be executed with `uv run`:
```console
$ uv run hello.py
Hello from example-project!
```
### Libraries
A library is a project that is intended to be built and distributed as a Python package, for
example, by uploading it to PyPI. A library provides functions and objects for other projects to
consume.
Libraries can be created by using the `--lib` flag:
```console
$ uv init --lib example-lib
$ tree example-lib
example-lib
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_lib
├── py.typed
└── __init__.py
```
When creating a library, uv defines a build system and places the source code in a `src` directory.
These changes ensure 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 code. The
project includes a package at `src/example_lib` that will be built and installed into the project
environment.
```toml title="pyproject.toml"
[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"
```
!!! note
uv does not provide a build backend yet. `hatchling` is used by default, but there are other
options. You may need to use the [hatch build](https://hatch.pypa.io/1.9/config/build/) options
to configure `hatchling` for your project structure.
Progress towards a uv build backend can be tracked in [astral-sh/uv#3957](https://github.com/astral-sh/uv/issues/3957).
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
$ uv run --directory example-lib python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
```
You can select a different build backend template by using `--build-backend` with `hatchling`,
`flit-core`, `pdm-backend`, `setuptools`, `maturin`, or `scikit-build-core`.
```console
$ uv init --lib --build-backend maturin example-lib
$ tree example-lib
example-lib
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
└── example_lib
├── py.typed
├── __init__.py
└── _core.pyi
```
And you can import and execute it using `uv run`:
```console
$ uv run --directory example-lib python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
```
!!! tip
Changes to `lib.rs` or `main.cpp` will require running `--reinstall` when using binary build
backends such as `maturin` and `scikit-build-core`.
### Packaged applications
The `--package` flag can be passed to `uv init` to create a distributable application, e.g., if you
want to publish a command-line interface via PyPI. uv will define a build backend for the project,
include a `[project.scripts]` entrypoint, and install the project package into the project
environment.
The project structure looks the same as a library:
```console
$ uv init --app --package example-packaged-app
$ tree example-packaged-app
example-packaged-app
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_packaged_app
└── __init__.py
```
But the module defines a CLI function:
```python title="__init__.py"
def main() -> None:
print("Hello from example-packaged-app!")
```
And the `pyproject.toml` includes a script entrypoint:
```toml title="pyproject.toml" hl_lines="9 10"
[project]
name = "example-packaged-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
[project.scripts]
example-packaged-app = "example_packaged_app:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
```
Which can be executed with `uv run`:
```console
$ uv run --directory example-packaged-app example-packaged-app
Hello from example-packaged-app!
```
!!! tip
An existing application can be redefined as a distributable package by adding a build system.
However, this may require changes to the project directory structure, depending on the build
backend.
In addition, you can further customize the build backend of a packaged application by specifying
`--build-backend` including binary build backends such as `maturin`.
```console
$ uv init --app --package --build-backend maturin example-packaged-app
$ tree example-packaged-app
example-packaged-app
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
└── example_packaged_app
├── __init__.py
└── _core.pyi
```
Which can also be executed with `uv run`:
```console
$ uv run --directory example-packaged-app example-packaged-app
Hello from example-packaged-app!
```