uv na macOS: zarządzanie wersjami Pythona, projektami i narzędziami
Tłumaczenie automatyczne Ten artykuł został automatycznie przetłumaczony z angielskiego oryginału.
Przeniosłem swój workflow Pythona na uv. Zastąpił przełączanie między pip, środowiskami wirtualnymi, pip-tools, pipx i menedżerami projektów. Jeden plik wykonywalny obsługuje teraz większość tych zadań.
Poszczególne workflow nadal się różnią. Dla programistów Pythona przechodzących na uv na macOS z pip, środowisk wirtualnych, pip-tools lub pipx projekt, skrypt z metadanymi inline, narzędzie jednorazowe i zainstalowany CLI należą do różnych środowisk i mają różny cykl życia. Poniższe polecenia pokazują, jak wybrać właściwe rozwiązanie.
Szybki start
# Install uv with Homebrew
brew install uv
# Start a project
uv init example-app
cd example-app
uv add httpx
uv run python main.py
# Run an isolated CLI without installing it permanently
uvx ruff check .
TL;DR. W projektach używam
uv add,uv lock,uv synciuv run. W przypadku samowystarczalnych skryptów używam metadanych PEP 723,uvxdo narzędzi jednorazowych, auv tool installdo poleceń, które muszą pozostać naPATH. W CI--lockedsprawdza, czy metadane projektu są zgodne zuv.lock.--frozenufa istniejącemu lockowi bez sprawdzania jego aktualności.
Instalacja uv z jednym właścicielem
Homebrew to wygodna metoda instalacji na macOS. Obsługiwane metody opisano w instrukcji instalacji uv:
brew install uv
uv --version
Jeśli uv został zainstalowany przez Homebrew, aktualizować go powinien Homebrew:
brew upgrade uv
uv self update jest przeznaczone dla niezależnej metody instalacji uv i jest wyłączone w przypadku instalacji za pomocą menedżerów pakietów. Nie pozwól, aby dwa instalatory konkurowały o ten sam plik wykonywalny.
Przydatne polecenia do sprawdzania tożsamości:
command -v uv
uv python dir
uv tool dir
uv cache dir
Zarządzane instalacje Pythona, trwałe narzędzia i jednorazowe wpisy cache mają osobne katalogi. Cache można usunąć i odbudować. Nie jest on źródłem prawdy.
Projekty: deklaracje, rozwiązywanie zależności i środowisko
Projekt uv zwykle składa się z trzech artefaktów:
pyproject.tomlzawiera metadane projektu i bezpośrednie wymagania.uv.lockprzechowuje wieloplatformowe rozwiązanie zależności uv..venvto lokalne zainstalowane środowisko, które powinno być usuwalne.
Utwórz aplikację i dodaj wymagania uruchomieniowe oraz testowe:
uv init forecast-app
cd forecast-app
uv add httpx
uv add --group test pytest
uv run python main.py
uv run --group test pytest
Bieżące szablony aplikacji uv tworzą main.py, pyproject.toml, README.md i .python-version. Domyślnie nie definiują systemu budowania. Użyj uv init --lib w przypadku biblioteki pakowanej z układem src i backendem budowania.
uv run sprawdza projekt, w razie potrzeby aktualizuje lock, synchronizuje wymagane zależności i uruchamia polecenie. Cykl życia opisano w dokumentacji układu projektu i synchronizacji uv. Pierwsza operacja na projekcie tworzy w razie potrzeby .venv i uv.lock. Samo uv init tworzy tylko pliki projektu.
Commituj dane wejściowe, nie środowisko
Commituj pyproject.toml, uv.lock, kod źródłowy oraz świadomie wybrany .python-version. Ignoruj .venv i cache uv.
Lock rejestruje rozwiązanie dla obsługiwanych markerów i platform. Nie sprawia, że natywne wheel’e są identyczne na macOS, Linuxie, procesorach Intel i Apple Silicon. Testuj każdą platformę wdrożeniową.
Aktualność locka: --locked to nie --frozen
!!! byte „Byte mówi”
Używałem `--frozen` w CI, aby pomijać rozwiązywanie zależności. Pomijało ono również sprawdzanie rozbieżności. Lock pozostawał niezgodny z `pyproject.toml` przez miesiąc i nic nie zasygnalizowało problemu.
Domyślnie polecenia projektu mogą aktualizować uv.lock, gdy zmienią się deklaracje. Informacje o flagach dotyczących aktualności i dokładności znajdziesz w dokumentacji blokowania i synchronizacji uv.
Użyj --locked, aby wymagać, by lock był aktualny względem metadanych projektu:
uv lock --check
uv sync --locked --group test
uv run --locked --group test pytest
Jeśli pyproject.toml i uv.lock są niezgodne, te polecenia zakończą się błędem zamiast rozwiązać i zapisać nowy lock. Zwykle właśnie taki mechanizm powinien pełnić funkcję bramki CI.
Używaj --frozen tylko wtedy, gdy celowo chcesz, aby uv użył istniejącego locka bez sprawdzania jego aktualności:
uv sync --frozen
Może to być przydatne w kontrolowanym etapie budowania, w którym lock został już zweryfikowany, ale nie wykrywa przestarzałego locka.
Dokładność to osobne ustawienie, niezależne od aktualności. uv sync jest domyślnie dokładne i usuwa nadmiarowe pakiety. uv run domyślnie wykonuje synchronizację niedokładną, chyba że zażądano --exact.
Zarządzany Python: żądanie wersji, nie uniwersalny plik binarny
uv może pobierać i zarządzać dystrybucjami Pythona:
uv python install 3.12 3.13
uv python list --only-installed
uv python pin 3.12
Zarządzane kompilacje CPythona uv pochodzą z projektu python-build-standalone. uv może również wykrywać interpretery systemowe, z Homebrew, pyenv, Conda i innych źródeł. Obsługiwane źródła i sposób wykrywania opisano w dokumentacji wersji Pythona uv.
.python-version to żądanie wersji wykrywane przez uv i inne kompatybilne narzędzia. requires-python w pyproject.toml to kontrakt zgodności projektu. Oba ustawienia powinny być świadome:
[project]
requires-python = ">=3.12,<3.14"
Przypięcie 3.12 nie gwarantuje wiecznie tej samej kompilacji patch ani tego samego artefaktu w każdym systemie operacyjnym. Gdy potrzebujesz konkretnej wersji patch, zażądaj jej dokładnie i spraw, aby CI jawnie wybierało oraz raportowało interpreter.
Użyj innego menedżera Pythona, gdy projekt wymaga dystrybucji lub konfiguracji kompilacji, których uv nie dostarcza. uv nadal może korzystać z takiego interpretera przez --python lub za pomocą zwykłego wykrywania.
Wybór między uv run, uvx i zainstalowanymi narzędziami
Narzędzia powiązane z projektem: uv run
Jeśli pytest, mypy, generator kodu lub inne narzędzie musi importować projekt albo korzystać z jego zablokowanych wtyczek, zadeklaruj je w grupie zależności:
uv add --group lint ruff
uv run --group lint ruff check .
Uruchomienie takiego narzędzia przez uvx odizolowałoby je od projektu i mogłoby ukryć zainstalowany pakiet lub wymagane wtyczki.
Narzędzia ad hoc: uvx
uvx to alias dla uv tool run. Tworzy izolowane środowisko przechowywane w usuwalnym cache uv. Dokumentacja narzędzi uv opisuje ten cache i cykl życia trwałych narzędzi:
uvx ruff@0.12.0 check .
uvx --from jupyterlab jupyter lab
uvx --with mkdocs-material mkdocs --help
Przypnij wersję narzędzia w CI lub dokumentacji. Pierwsze wywołanie bez wersji wybiera bieżące wydanie, a późniejsze wywołania mogą ponownie używać stanu cache.
Trwałe pliki wykonywalne: uv tool install
Zainstaluj narzędzie, gdy kontrolowane przez Ciebie skrypty potrzebują jego polecenia na PATH albo gdy manifest konfiguracji maszyny powinien nim zarządzać:
uv tool install ruff
uv tool list
uv tool upgrade ruff
uv tool uninstall ruff
Trwałe narzędzia nadal korzystają z izolowanych środowisk. Nie modyfikuj tych środowisk ręcznie za pomocą pip.
Skrypty: uczyń jeden plik jednostką wydania
PEP 723 definiuje metadane skryptu inline. Kompatybilny runner może odczytać blok komentarza i zbudować izolowane środowisko. Informacje o formacie metadanych i zachowaniu runnera znajdziesz w przewodniku po skryptach uv oraz w PEP 723.
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "httpx>=0.27,<1",
# ]
# ///
import httpx
response = httpx.get("https://example.com", timeout=10)
response.raise_for_status()
print(response.status_code)
Uruchamiaj skrypt i edytuj metadane za pomocą uv:
uv run fetch.py
uv add --script fetch.py rich
uv remove --script fetch.py rich
Zwykły python fetch.py ignoruje metadane w komentarzu. Skrypt zależy więc od kompatybilnego runnera, mimo że składnia Pythona pozostaje poprawna.
Jeśli skrypt ma później odtwarzać to samo rozwiązanie zależności, utwórz sąsiedni lock:
uv lock --script fetch.py
uv run --script fetch.py
Spowoduje to zapisanie fetch.py.lock. Znacznik czasu exclude-newer może ograniczać daty dystrybucji branych pod uwagę, ale jest słabszy niż dokładnie zablokowane rozwiązanie i nie gwarantuje, że dany artefakt pozostanie dostępny.
Wybierz projekt, gdy kilka plików współdzieli zależności, kod można importować jako pakiet, testy wymagają stanu projektu lub kilka skryptów musi być wdrażanych razem.
Pliki requirements: kompatybilność, nie gwarancja niezmienności
Plik requirements.txt może zawierać luźne dane wejściowe, dokładne przypięcia, hashe, ograniczenia, indeksy, URL-e lub eksport requirements wygenerowany przez resolver. Jego odtwarzalność zależy od sposobu utworzenia i użycia. Sama nazwa pliku niczego nie mówi.
Korzystaj z interfejsu uv kompatybilnego z pip bez migracji:
uv venv
uv pip sync requirements.txt
uv run python app.py
uv pip sync dopasowuje środowisko do pliku. uv pip install -r dodaje pakiety, ale nie usuwa istniejących.
W przypadku zarządzanej aplikacji przydatna może być migracja etapowa:
uv init --bare
uv add -r requirements.in
uv add --group test -r requirements-test.in
uv lock
uv sync --locked
Przed usunięciem starych plików uruchom pełną ścieżkę testowania i wdrażania. Jeśli system downstream nadal wymaga formatu pip, wygeneruj go ze zweryfikowanego locka uv za pomocą polecenia eksportu uv:
uv export --format requirements.txt \
--output-file requirements.txt
Nie utrzymuj uv.lock i ręcznie edytowanego eksportu jako dwóch konkurencyjnych rozwiązań zależności.
Cache, indeksy i granice łańcucha dostaw
Cache uv przyspiesza kolejne instalacje, ale nadal można go bezpiecznie usunąć:
uv cache prune
uv cache clean
Do rutynowego czyszczenia preferuj prune. clean usuwa wszystkie wpisy cache i wymusza późniejsze pobieranie oraz budowanie.
Lockfile poprawia powtarzalność. Nie sprawia jednak, że zależności stają się godne zaufania. Przeglądaj źródła pakietów, konfigurację indeksów, rewizje Git, backendy budowania, licencje i dane uwierzytelniające. Nie umieszczaj uwierzytelnionej konfiguracji indeksów w commitowanych plikach. Wyjątkiem jest niejawna wartość sekretu referencja do zatwierdzonego mechanizmu obsługi poświadczeń.
W przypadku pakietów natywnych zapisuj architekturę wdrożeniową i sprawdzaj dostępność wheel’i. W przeciwnym razie resolver może przejść do budowania ze źródeł, które wymaga kompilatorów i bibliotek systemowych nieobecnych w CI lub produkcji.
Zwięzła lista kontrolna
Dla każdego projektu:
- Zdefiniuj
requires-pythoni bezpośrednie zależności wpyproject.toml. - Oddziel publikowane extras od lokalnych grup zależności.
- Commituj
uv.lock. Ignoruj.venvi stan cache. - Uruchamiaj narzędzia powiązane z projektem przez środowisko projektu.
- Używaj w CI
uv lock --checklub--locked. - Testuj każdy docelowy system operacyjny i architekturę reprezentowane przez lock.
- Eksportuj formaty kompatybilności wyłącznie dla wskazanych odbiorców downstream.
- Niezależnie od rozwiązywania zależności weryfikuj zasady dotyczące źródeł i poświadczeń.
uv jest najbardziej użyteczne, gdy te granice własności pozostają widoczne. Jeden plik binarny może zarządzać nimi wszystkimi, nie zamieniając ich w jedno środowisko. Mniej narzędzi, a cztery workflow pozostają rozdzielone. Dlatego nadal używam uv jako domyślnego narzędzia do projektów Pythona na macOS.