1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357# [Creating projects](#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](#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`. The working directory can be modified with the `--directory` option, which will cause the target directory path to 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.
## [Applications](#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.
```
$ 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`).
```
$ 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/#project-packaging) and will not be installed into the environment:
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:
main.py
```
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
```
Python files can be executed with `uv run`:
```
$ cd example-app
$ uv run main.py
Hello from example-project!
```
## [Packaged applications](#packaged-applications)
Many use-cases require a [package](../config/#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:
```
$ uv init --package example-pkg
```
The source code is moved into a `src` directory with a module directory and an `__init__.py` file:
```
$ tree example-pkg
example-pkg
โโโ .python-version
โโโ README.md
โโโ pyproject.toml
โโโ src
โโโ example_pkg
โโโ __init__.py
```
A [build system](../config/#build-systems) is defined, so the project will be installed into the environment:
pyproject.toml
```
[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 = ["uv_build>=0.9.26,<0.10.0"]
build-backend = "uv_build"
```
Tip
The `--build-backend` option can be used to request an alternative build system.
A [command](../config/#entry-points) definition is included:
pyproject.toml
```
[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 = ["uv_build>=0.9.26,<0.10.0"]
build-backend = "uv_build"
```
The command can be executed with `uv run`:
```
$ cd example-pkg
$ uv run example-pkg
Hello from example-pkg!
```
## [Libraries](#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:
```
$ 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:
```
$ 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/#build-systems) is defined, so the project will be installed into the environment:
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 = ["uv_build>=0.9.26,<0.10.0"]
build-backend = "uv_build"
```
Tip
You can select a different build backend template by using `--build-backend` with `hatchling`, `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).
The created module defines a simple API function:
__init__.py
```
def hello() -> str:
return "Hello from example-lib!"
```
And you can import and execute it using `uv run`:
```
$ cd example-lib
$ uv run python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
```
## [Projects with extension modules](#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:
```
$ 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:
```
$ 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:
src/lib.rs
```
use pyo3::prelude::*;
#[pymodule]
mod _core {
use pyo3::prelude::*;
#[pyfunction]
fn hello_from_bin() -> String {
"Hello from example-ext!".to_string()
}
}
```
And the Python module imports it:
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`:
```
$ cd example-ext
$ uv run example-ext
Hello from example-ext!
```
Important
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`.
## [Creating a minimal project](#creating-a-minimal-project)
If you only want to create a `pyproject.toml`, use the `--bare` option:
```
$ 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`).
```
$ tree example-bare
example-bare
โโโ pyproject.toml
```
uv will also not add extra metadata to the `pyproject.toml`, such as the `description` or `authors`.
```
[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:
```
$ uv init example --bare --description "Hello world" --author-from git --vcs git --python-pin
```