프로젝트 생성¶
uv는 uv init
명령어로 프로젝트를 생성하는 기능을 지원한다.
프로젝트를 생성할 때 uv는 두 가지 기본 템플릿을 제공한다: 애플리케이션과 라이브러리. 기본적으로 uv는 애플리케이션 프로젝트를 생성한다. --lib
플래그를 사용하면 라이브러리 프로젝트를 생성할 수 있다.
대상 디렉토리¶
uv는 작업 디렉토리에 프로젝트를 생성하거나, 이름을 제공하여 대상 디렉토리에 프로젝트를 만들 수 있다. 예를 들어, uv init foo
와 같은 명령어를 사용할 수 있다. 대상 디렉토리에 이미 프로젝트가 존재하는 경우, 즉 pyproject.toml
파일이 있는 경우, uv는 오류와 함께 종료된다.
애플리케이션¶
애플리케이션 프로젝트는 웹 서버, 스크립트, 커맨드라인 인터페이스에 적합하다.
uv init
명령어는 기본적으로 애플리케이션을 대상으로 하지만, --app
플래그를 사용해 명시적으로 지정할 수도 있다.
$ uv init example-app
이 명령어는 pyproject.toml
, 샘플 파일(main.py
), README 파일, 그리고 Python 버전 고정 파일(.python-version
)을 포함한 프로젝트를 생성한다.
$ tree example-app
example-app
├── .python-version
├── README.md
├── main.py
└── pyproject.toml
Note
v0.6.0 이전 버전에서는 main.py
대신 hello.py
파일을 생성했다.
pyproject.toml
파일에는 기본 메타데이터가 포함된다. 빌드 시스템은 포함하지 않으며, 패키지로 간주되지 않아 환경에 설치되지 않는다.
[project]
name = "example-app"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
샘플 파일은 표준 보일러플레이트를 포함한 main
함수를 정의한다.
def main():
print("Hello from example-app!")
if __name__ == "__main__":
main()
Python 파일은 uv run
명령어로 실행할 수 있다.
$ uv run main.py
Hello from example-project!
패키지화된 애플리케이션¶
많은 사용 사례에서 패키지가 필요하다. 예를 들어 PyPI에 게시할 커맨드라인 인터페이스를 만들거나, 특정 디렉터리에 테스트를 정의하려는 경우가 있다.
--package
플래그를 사용해 패키지화된 애플리케이션을 생성할 수 있다:
$ uv init --package example-pkg
소스 코드는 src
디렉터리로 이동하며, 모듈 디렉터리와 __init__.py
파일이 생성된다:
$ tree example-pkg
example-pkg
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_packaged_app
└── __init__.py
빌드 시스템이 정의되어 프로젝트가 환경에 설치된다:
[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_packaged_app:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Tip
--build-backend
옵션을 사용해 다른 빌드 시스템을 요청할 수 있다.
커맨드 정의가 포함된다:
[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_packaged_app:main"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
커맨드는 uv run
으로 실행할 수 있다:
$ uv run --directory example-pkg example-pkg
Hello from example-pkg!
라이브러리¶
라이브러리는 다른 프로젝트에서 사용할 수 있는 함수와 객체를 제공한다. 라이브러리는 PyPI와 같은 플랫폼에 업로드하여 배포할 목적으로 만들어진다.
--lib
플래그를 사용해 라이브러리를 생성할 수 있다:
$ uv init --lib example-lib
Note
--lib
플래그는 --package
를 암시한다. 라이브러리는 항상 패키지화된 프로젝트를 필요로 한다.
패키지화된 애플리케이션과 마찬가지로, src
레이아웃을 사용한다. py.typed
마커를 포함해 라이브러리에서 타입을 읽을 수 있음을 소비자에게 알린다:
$ tree example-lib
example-lib
├── .python-version
├── README.md
├── pyproject.toml
└── src
└── example_lib
├── py.typed
└── __init__.py
Note
라이브러리를 개발할 때 src
레이아웃은 특히 유용하다. 이 레이아웃은 라이브러리가 프로젝트 루트의 python
호출과 격리되도록 보장하며, 배포된 라이브러리 코드가 프로젝트 소스의 나머지 부분과 명확히 분리되도록 한다.
빌드 시스템이 정의되어 있어 프로젝트가 환경에 설치된다:
[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
--build-backend
와 함께 hatchling
, flit-core
, pdm-backend
, setuptools
, maturin
, 또는 scikit-build-core
를 사용해 다른 빌드 백엔드 템플릿을 선택할 수 있다. 확장 모듈이 있는 라이브러리를 만들려면 대체 백엔드가 필요하다.
생성된 모듈은 간단한 API 함수를 정의한다:
def hello() -> str:
return "Hello from example-lib!"
uv run
을 사용해 이를 임포트하고 실행할 수 있다:
$ uv run --directory example-lib python -c "import example_lib; print(example_lib.hello())"
Hello from example-lib!
확장 모듈을 사용하는 프로젝트¶
대부분의 Python 프로젝트는 '순수 Python'으로 이루어져 있다. 이는 C, C++, FORTRAN, Rust와 같은 다른 언어로 모듈을 정의하지 않는다는 의미다. 하지만 성능이 중요한 코드에서는 확장 모듈을 사용하는 프로젝트가 자주 활용된다.
확장 모듈이 포함된 프로젝트를 만들려면 대체 빌드 시스템을 선택해야 한다. uv는 다음과 같은 확장 모듈 빌드를 지원하는 빌드 시스템을 사용한 프로젝트 생성 기능을 제공한다:
- Rust 프로젝트를 위한
maturin
- C, C++, FORTRAN, Cython 프로젝트를 위한
scikit-build-core
빌드 시스템은 --build-backend
플래그로 지정한다:
$ uv init --build-backend maturin example-ext
Note
--build-backend
를 사용하면 --package
가 자동으로 적용된다.
이 프로젝트에는 일반 Python 프로젝트 파일 외에도 Cargo.toml
과 lib.rs
파일이 포함된다:
$ tree example-ext
example-ext
├── .python-version
├── Cargo.toml
├── README.md
├── pyproject.toml
└── src
├── lib.rs
└── example_ext
├── __init__.py
└── _core.pyi
Note
scikit-build-core
를 사용하는 경우 CMake 설정 파일과 main.cpp
파일을 볼 수 있다.
Rust 라이브러리는 간단한 함수를 정의한다:
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(())
}
Python 모듈은 이 함수를 불러온다:
from example_ext._core import hello_from_bin
def main() -> None:
print(hello_from_bin())
이 명령어는 uv run
으로 실행할 수 있다:
$ uv run --directory example-ext example-ext
Hello from example-ext!
Important
lib.rs
나 main.cpp
의 확장 코드를 변경한 경우, --reinstall
을 실행해 다시 빌드해야 한다.
최소 프로젝트 생성하기¶
pyproject.toml
파일만 생성하려면 --bare
옵션을 사용한다:
$ uv init example --bare
uv는 Python 버전 고정 파일, README, 그리고 소스 디렉터리나 파일을 생성하지 않는다. 또한 버전 관리 시스템(예: git
)도 초기화하지 않는다.
$ tree example-bare
example-bare
└── pyproject.toml
uv는 pyproject.toml
에 description
이나 authors
같은 추가 메타데이터도 포함하지 않는다.
[project]
name = "example"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []
--bare
옵션은 --lib
나 --build-backend
같은 다른 옵션과 함께 사용할 수 있다. 이 경우 uv는 여전히 빌드 시스템을 구성하지만, 일반적인 파일 구조는 생성하지 않는다.
--bare
옵션을 사용할 때도 추가 기능을 선택적으로 사용할 수 있다:
$ uv init example --bare --description "Hello world" --author-from git --vcs git --python-pin