서론
python의 패키지 관리자는 pip -> poetry -> pdm 등 많은 것들이 등장했고,
Rust의 인기를 업고 uv가 등장했다.
pip대비 10 ~100배의 속도 & python 설치 및 관리라는 매력적인 특성이 있다.
목표
- 어떤 기능을 제공하는지 정리
- 기존의 어떤 문제점을 해결했는지 이해
핵심 명령어
1. 프로젝트 생성
# 애플리케이션 생성
uv init {app_name}
# 라이브러리 생성
uv init --lib {lib_name}
# 확장 모듈 생성 (maturin: Rust, scikit-build-core: C계열)
uv init --build-backend maturin {ext_name}
배포용인 프로젝트와, 아닌 프로젝트를 구분할 수 있게 해준다.
Rust나, C기반의 성능이 중요한 프로젝트를 쉽게 개발할 수 있게 해준다.
2. Python 관리
#Python 설치
uv python install 3.11
#Python 버전 고정
uv python pin
Python의 버전이 일치하지 않아서 발생하는 문제와
여러 버전을 테스트할 때의 번거로움을 해소한다.
3. dependency 관리
# 스크립트 의존성 추가
uv add --script example.py 'requests<3' 'rich'
# 프로젝트 의존성 추가
uv add requests
# 프로젝트 의존성 제거
uv remove requests
# 개발용 의존성 추가
uv add --dev pytest
# 의존성 리스트 확인
uv tree
# OS, Python-version별 의존성 추가
uv add "jax; sys_platform == 'linux'"
uv add "numpy; python_version >= '3.11'"
원하는 기능을 구현하기 위해서 여러 라이브러리를 테스트 할 때가 있다.
그러다 보면 의존성이 지저분해 지는 문제가 있다.
스크립트에 임시로 의존성을 추가하고, 사용이 결정되면 프로젝트에 추가하는 방식으로 작업하면
의존성이 더러워지는 문제점을 해소한다.
그리고 개발용 의존성과, 사용을 위한 의존성을 깔끔하게 분리할 수 있다.
스크립트를 순차적으로 동작시키는 작업에서,
의존성의 충돌이 발생하는 경우, 스크립트 별 의존성을 사용하여 회피할 수 있다.
4. 스크립트 실행
# uv로 코드 실행
uv run example.py
# 특정 Python 버전 실행
uv run --python 3.10 example.py
# 종속성 주입 실행
uv run --with requests example.py
python 버전, 외부 의존성 주입을 통해
환경에 독립된 원하는 환경의 실행을 할 수 있다.
5. 잠금 및 동기화
# 의존성 고정
uv lock
# 의존성 동기화
uv sync
단순 의존성 뿐 아니라, 버전과 OS의 차이까지 고려하여
재현성을 향상시킨다.
6.Entry points지정
# projevt.toml
[project.scripts]
hello = "example:hello"
uv run hello
실행할 파일을 복잡하게 경로를 입력할 필요 없이
매핑을 통해 손쉽게 실행할 수 있다.
7. Cargo스타일 워크스페이스
# 라이브러리 폴더 내에서 다시
uv init
# 격리 워크 스페이스
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]
[tool.uv.sources]
bird-feeder = { workspace = true }
[tool.uv.workspace]
members = ["packages/*"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
# 경로기반 격리 워크 스페이스
[project]
name = "albatross"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = ["bird-feeder", "tqdm>=4,<5"]
[tool.uv.sources]
bird-feeder = { path = "packages/bird-feeder" }
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
모노레포, MSA와 같은 구조에서
프로젝트 단위로 의존성을 관리할 수 있게 해준다.
프로젝트끼리 같은 의존성을 사용하면, 경로 지정을 통해 따로 관리하지 않고도 사용할 수 있다.