uv na macOS: zarządzanie wersjami Pythona, projektami i narzędziami
Tłumaczenie automatyczne
Ten artykuł został automatycznie przetłumaczony z angielskiego oryginału.
Ten poradnik jest dla programistów Pythona na macOS, którzy przechodzą z pip, venv, pip-tools, pyenv lub pipx na uv. uv obsługuje cztery rodzaje pracy: projekt, skrypt w jednym pliku, jednorazowe uruchomienie CLI przez uvx i CLI zainstalowane w PATH. Wszystkie cztery mogą korzystać z wersji Pythona instalowanych przez uv. Poznasz polecenia dla każdego z nich i dowiesz się, jak wybrać odpowiedni wariant.
Zacząłem używać uv w swojej pracy z Pythonem. Jeden plik wykonywalny obsługuje teraz pracę, którą wcześniej dzieliłem między te narzędzia.
Szybki start
# Install uv with Homebrew
brew install uv
# Start a project
uv init --no-package example-app
cd example-app
uv add httpx
uv run python main.py
# Prints "Hello from example-app!"
# Run an isolated CLI without installing it permanently
uvx ruff check .
Diagram pokazuje, gdzie każdy z czterech sposobów pracy trzyma swoje środowisko, co zostaje po każdym z nich i zarządzane instalacje Pythona, które współdzielą.
Instalacja i aktualizacja uv
Homebrew to wygodny sposób instalacji na macOS. Obsługiwane metody opisuje przewodnik instalacji uv:
brew install uv
uv --version
Jeśli uv zainstalował Homebrew, Homebrew powinien go też aktualizować:
brew upgrade uv
uv self update służy do samodzielnej metody instalacji uv i jest wyłączone w instalacjach przez menedżery pakietów. Aktualizuj uv tym samym narzędziem, którym go zainstalowano.
Aby sprawdzić, gdzie znajdują się uv, jego instalacje Pythona, narzędzia i pamięć podręczna:
command -v uv
uv python dir
uv tool dir
uv cache dir
Zarządzane instalacje Pythona, trwałe narzędzia i usuwalne wpisy pamięci podręcznej mają osobne katalogi. Pamięć podręczną można usunąć i odbudować. Nie jest ona źródłem danych referencyjnych. Na macOS uv klonuje pakiety z pamięci podręcznej do każdego środowiska (kopiowanie przy zapisie), zamiast je kopiować. Odbudowa .venv wykorzystuje ponownie potrzebne artefakty, które nadal są w pamięci podręcznej.
Projekty: deklaracje, rozwiązywanie zależności i środowisko
Projekt uv ma zwykle trzy części:
pyproject.tomldeklaruje metadane projektu i bezpośrednie wymagania.uv.lockprzechowuje wieloplatformowe rozwiązanie zależności uv..venvto lokalne zainstalowane środowisko, które powinno dać się w każdej chwili usunąć.
Diagram dzieli pliki projektu według tego, kto je zapisuje i czy git je przechowuje.
Utwórz aplikację i dodaj zależności potrzebne do działania i testowania:
uv init --no-package forecast-app
cd forecast-app
uv add httpx
uv add --group test pytest
uv run python main.py
uv run --group test pytest --version
Aplikacja wypisuje Hello from forecast-app!; ostatnie polecenie sprawdza, czy pytest jest zainstalowany. Gdy masz już testy, uruchom je przez uv run --group test pytest.
Szablon --no-package tworzy main.py, pyproject.toml, README.md i .python-version bez systemu budowania. Od uv 0.12 zwykłe uv init tworzy aplikację jako pakiet z układem src i backendem budowania. Użyj uv init --lib dla biblioteki jako pakietu. Zobacz poradnik tworzenia projektów w uv.
uv run sprawdza projekt, w razie potrzeby aktualizuje plik lock, synchronizuje wymagane zależności i uruchamia polecenie. Ten cykl opisuje dokumentacja 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.
uv domyślnie instaluje grupę dev. Inne grupy, takie jak test, wymagają --group przy każdym poleceniu albo default-groups w sekcji [tool.uv]. Aby zainstalować tylko jedną grupę, na przykład w zadaniu CI dla dokumentacji, użyj uv sync --only-group docs.
Grupy pozostają lokalne i nigdy nie są publikowane. Opublikowany extra działa inaczej: uv add --optional cli rich dodaje extra, które użytkownicy instalują jako forecast-app[cli].
Aby używać projektu w notatnikach Jupyter w VS Code, uruchom uv add --dev ipykernel i wybierz .venv jako kernel. Zobacz przewodnik uv po Jupyterze.
Commituj dane wejściowe, nie środowisko
Commituj pyproject.toml, uv.lock, kod źródłowy i celowo ustawiony .python-version. Ignoruj .venv i cache uv.
Członek zespołu, który sklonuje repozytorium, jednym poleceniem dostaje środowisko zgodne z plikiem lock:
git clone https://github.com/example/forecast-app.git
cd forecast-app
uv sync --locked
Aby sprawdzić, dlaczego pakiet jest zainstalowany, i przenieść plik lock na nowsze wersje:
uv tree # show the dependency graph
uv tree --outdated # show newer versions where they exist
uv lock --upgrade-package httpx # move one package, keep the rest
uv lock --upgrade # re-resolve everything
Commituj zmieniony uv.lock razem ze zmianą, która go wymagała.
Plik lock zapisuje rozwiązanie zależności dla obsługiwanych markerów i platform. Nie sprawia, że natywne wheele są identyczne na macOS, Linuksie, Intelu i Apple Silicon. Testuj każdą platformę wdrożeniową.
Część tego uv potrafi wymusić. required-environments w sekcji [tool.uv] sprawia, że rozwiązywanie zależności kończy się błędem, gdy pakiet bez dystrybucji źródłowej nie ma wheela dla wymienionej platformy:
[tool.uv]
required-environments = [
"sys_platform == 'darwin' and platform_machine == 'arm64'",
"sys_platform == 'linux' and platform_machine == 'x86_64'",
]
no-build-package zabrania budowania ze źródeł dla wskazanych pakietów, więc brakujący wheel powoduje błąd instalacji zamiast uruchomienia kompilatora. Jeśli wdrażasz też PyTorch na Linuksie z CUDA, skonfiguruj indeks według przewodnika uv po PyTorch.
Aktualność pliku lock: --locked to nie --frozen
Domyślnie polecenia projektu mogą aktualizować uv.lock, gdy zmieniają się deklaracje. Flagi aktualności i dokładności opisuje dokumentacja uv o blokowaniu i synchronizacji.
Użyj --locked, aby wymagać, by plik lock był zgodny z metadanymi projektu:
uv lock --check
uv sync --locked --group test
uv run --locked --group test pytest
Jeśli pyproject.toml i uv.lock się nie zgadzają, te polecenia kończą się błędem zamiast tworzyć nowy plik lock. Używaj ich w CI, aby nieaktualny plik lock przerywał budowanie.
Używaj --frozen tylko wtedy, gdy celowo chcesz, by uv użył istniejącego pliku lock bez sprawdzania, czy jest aktualny:
uv sync --frozen
Może to być przydatne w kontrolowanym etapie budowania, w którym plik lock został już sprawdzony, ale nie wykrywa to nieaktualnego pliku lock.
Diagram śledzi jeden nieaktualny projekt przez cztery polecenia: rich dodano ręcznie do pyproject.toml, a uv.lock nie został zaktualizowany.
Dokładność to ustawienie niezależne od aktualności. uv sync jest domyślnie dokładne i usuwa zbędne pakiety. uv run domyślnie używa niedokładnej synchronizacji, chyba że podasz --exact. Diagram śledzi jeden ręcznie zainstalowany pakiet przez uv sync, uv run i uv run --exact.
Instalacja i przypinanie wersji Pythona
uv potrafi pobierać dystrybucje Pythona i nimi zarządzać:
uv python install 3.12 3.13
uv python list --only-installed
uv python pin 3.12
Zarządzane kompilacje CPython w uv pochodzą z projektu python-build-standalone. uv potrafi też znaleźć interpretery systemowe, z Homebrew, pyenv, Condy i inne. Obsługiwane źródła i sposób wyszukiwania opisuje dokumentacja uv o wersjach Pythona.
.python-version to żądanie wersji, które odczytują uv i inne zgodne narzędzia. uv python pin zapisuje ten plik, a uv init go tworzy. requires-python w pyproject.toml to kontrakt zgodności projektu. Ustawiaj oba świadomie:
[project]
requires-python = ">=3.12,<3.14"
uv bierze żądaną wersję najpierw z --python, potem z .python-version, a na końcu z requires-python.
Przypięcie 3.12 nie gwarantuje na zawsze tej samej kompilacji wersji z poprawkami ani tego samego artefaktu na każdym systemie operacyjnym. Jeśli potrzebujesz dokładnej wersji poprawki, podaj ją. W CI wybierz interpreter i wypisz go, przez uv run --python 3.12.7 python -VV albo ustawiając UV_PYTHON=3.12.7 dla zadania.
Użyj innego menedżera Pythona, gdy projekt potrzebuje dystrybucji lub konfiguracji budowania, której uv nie dostarcza. uv nadal może korzystać z takiego interpretera przez --python lub zwykłe wyszukiwanie.
Wybór między uv run, uvx a zainstalowanymi narzędziami
Wybierz według tego, czy narzędzie potrzebuje zainstalowanych pakietów projektu, musi pozostać w PATH, czy może działać niezależnie. Schemat pokazuje dostępne zależności i czas istnienia każdego środowiska.
Narzędzia powiązane z projektem: uv run
Jeśli pytest, mypy, generator kodu lub inne narzędzie musi importować projekt albo używać jego wtyczek w wersjach z pliku lock, zadeklaruj je w grupie zależności:
uv add --group lint ruff
uv run --group lint ruff check .
uvx nie instaluje automatycznie pakietu ani zależności projektu. Narzędzie nadal może importować lokalne pliki źródłowe, jeśli pozwala na to jego sposób importowania; użyj uv run, gdy potrzebuje zainstalowanego projektu lub jego zależności.
Narzędzia doraźne: uvx
uvx jest aliasem uv tool run. Wykorzystuje ponownie zgodne narzędzie zainstalowane przez uv tool install; w przeciwnym razie używa izolowanego środowiska w usuwalnej pamięci podręcznej uv. Dokumentacja narzędzi uv opisuje tę pamięć podręczną i cykl życia trwałych narzędzi:
uvx ruff@0.12.0 check .
uvx ruff@latest check .
uvx --from jupyterlab jupyter lab
uvx --from httpie http --version
uvx --with mkdocs-material mkdocs --help
Przypnij wersję narzędzia w CI lub dokumentacji. Jeśli narzędzie nie jest zainstalowane, pierwsze wywołanie bez wersji wybiera najnowsze dostępne wydanie; kolejne mogą wykorzystać stan pamięci podręcznej. @latest pomija zainstalowaną wersję i odświeża pamięć podręczną dla najnowszego wydania. Użyj --from, gdy nazwa pakietu różni się od nazwy polecenia, jak w przypadku jupyterlab i httpie.
Trwałe pliki wykonywalne: uv tool install
Zainstaluj narzędzie, gdy skrypty, nad którymi nie masz kontroli, potrzebują jego polecenia w PATH albo gdy ma nim zarządzać manifest konfiguracji twojej maszyny:
uv tool install ruff
uv tool list
uv tool upgrade ruff
uv tool upgrade --all
uv tool uninstall ruff
Jeśli instalacja ostrzega, że katalog plików wykonywalnych nie znajduje się w PATH, uruchom uv tool update-shell i uruchom powłokę ponownie przed użyciem polecenia. Zobacz dokumentację plików wykonywalnych narzędzi uv.
Trwałe narzędzia też używają izolowanych środowisk. Nie modyfikuj tych środowisk ręcznie przez pip.
Skrypty w jednym pliku z PEP 723
PEP 723 definiuje metadane skryptu inline. Zgodny runner potrafi odczytać blok komentarza i zbudować izolowane środowisko. Format metadanych i działanie runnera opisują przewodnik uv po skryptach oraz PEP 723.
Diagram zaznacza blok metadanych w fetch.py i pokazuje, co uv run i zwykły python robią z tym plikiem.
uv może napisać blok metadanych za ciebie:
uv init --script fetch.py --python 3.12
Gotowy skrypt wygląda tak:
# /// 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 przez uv:
uv run fetch.py
uv add --script fetch.py rich
uv remove --script fetch.py rich
Zwykłe python fetch.py ignoruje metadane w komentarzu. Skrypt zależy więc od zgodnego runnera, choć składnia Pythona pozostaje poprawna. uv to jeden z runnerów. pipx run, Hatch i PDM też odczytują ten blok.
Aby uruchamiać skrypt jako ./fetch.py, dodaj shebang, który wywołuje uv:
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["httpx"]
# ///
import httpx
chmod +x fetch.py
./fetch.py
Flaga -S sprawia, że env dzieli linię na osobne argumenty, więc --script trafia do uv.
Do szybkiego eksperymentu podaj zależności w linii poleceń zamiast pisać metadane. Druga linia uruchamia REPL Pythona z dostępnym pandas:
uv run --with httpx scratch.py
uv run --with pandas python
Dla skryptu, który ma później odtworzyć to samo rozwiązanie zależności, utwórz obok niego plik lock:
uv lock --script fetch.py
uv run --script fetch.py
To zapisuje fetch.py.lock. Znacznik czasu exclude-newer w bloku metadanych sprawia, że uv ignoruje wersje pakietów opublikowane po tej dacie:
# /// script
# dependencies = ["httpx"]
# [tool.uv]
# exclude-newer = "2025-04-17T00:00:00Z"
# ///
Daje to słabszą gwarancję niż plik lock. Nie przypina dokładnych wersji i nie przywróci pliku, który indeks później usunie.
Zamiast skryptu użyj projektu, gdy kilka plików współdzieli zależności, kod da się importować jako pakiet, testy potrzebują stanu projektu lub kilka skryptów musi zmieniać się razem.
Istniejące projekty z requirements.txt
Plik requirements.txt może zawierać luźne wymagania, dokładnie przypięte wersje, skróty kryptograficzne, ograniczenia, indeksy, adresy URL lub eksport wymagań wygenerowany przez resolver. Jego powtarzalność zależy od tego, jak go wygenerowano i jak się go używa. Sama nazwa pliku nic o tym nie mówi.
Masz dwie opcje: zachować format pip i uruchamiać go przez uv pip albo, dla własnej aplikacji, przejść na uv.lock.
Dla w pełni rozwiązanej listy bezpośrednich i przechodnich zależności użyj interfejsu uv zgodnego z pip bez migracji:
uv venv
uv pip sync requirements.txt
.venv/bin/python app.py
Uruchom tutaj zainstalowany interpreter bezpośrednio. Jeśli istnieje pyproject.toml, uv run może przed wykonaniem ustalić i zsynchronizować jego wymagania, zastępując właśnie zainstalowane pakiety. Zobacz poradnik skryptów uv.
uv pip sync dopasowuje środowisko do w pełni rozwiązanej listy zależności. Jeśli requirements.txt zawiera tylko wymagania bezpośrednie, użyj uv pip install -r requirements.txt, aby rozwiązać i zainstalować ich zależności. uv pip install -r dodaje pakiety. Zobacz poradnik blokowania wersji uv zgodny z pip.
W przypadku aplikacji, którą sam utrzymujesz, przydatna może być migracja etapami:
uv init --bare
uv add -r requirements.in
uv add --group test -r requirements-test.in
uv lock
uv sync --locked
Zanim usuniesz stare pliki, uruchom pełne testy i całą ścieżkę wdrożenia. Jeśli system zależny od projektu nadal oczekuje formatu pip, wygeneruj go ze sprawdzonego pliku lock uv za pomocą polecenia export 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 i prywatne indeksy
Cache uv przyspiesza powtarzane instalacje, ale nadal można go usunąć:
uv cache prune
uv cache clean
Do rutynowego sprzątania wybieraj prune. clean usuwa wszystkie wpisy cache i wymusza ponowne pobieranie i budowanie.
Plik lock poprawia powtarzalność. Nie sprawia, że zależności stają się godne zaufania.
Dla prywatnego indeksu umieść jego nazwę i adres URL w pyproject.toml, a dane uwierzytelniające trzymaj poza plikiem:
[[tool.uv.index]]
name = "internal"
url = "https://pypi.example.com/simple"
Przekazuj dane uwierzytelniające przez UV_INDEX_INTERNAL_USERNAME i UV_INDEX_INTERNAL_PASSWORD albo przez keyring. uv tworzy nazwy zmiennych z nazwy indeksu. Zobacz dokumentację uv o uwierzytelnianiu w indeksach.
Stare polecenia i ich odpowiedniki w uv
Jeśli przechodzisz ze starszych narzędzi, ta tabela przypisuje każdemu znanemu poleceniu polecenie uv, które wykonuje to samo zadanie.
| Zadanie | Wcześniej | uv |
|---|---|---|
| Instalacja Pythona | pyenv install 3.12 | uv python install 3.12 |
| Nowy projekt i środowisko | mkdir proj && cd proj && python -m venv .venv | uv init proj && cd proj && uv sync |
| Dodanie pakietu | pip install pandas && pip freeze > requirements.txt | uv add pandas |
| Przypięcie wersji | pip-compile requirements.in | uv lock |
| Aktualizacja jednego pakietu | pip-compile --upgrade-package httpx | uv lock --upgrade-package httpx |
| Uruchomienie w środowisku | source .venv/bin/activate && python app.py | uv run app.py |
| Skrypt z zależnościami | ręcznie utworzone venv dla jednego pliku | blok PEP 723 + uv run |
| Jednorazowe uruchomienie narzędzia | pipx run black | uvx black |
| Instalacja narzędzia | pipx install ruff | uv tool install ruff |
| Powtarzalna instalacja w CI | pip install -r requirements.txt | uv sync --locked |
Krótka lista kontrolna
Dla każdego projektu:
- Zdefiniuj
requires-pythoni bezpośrednie zależności wpyproject.toml. - Oddziel publikowane extras (
--optional) od lokalnych grup zależności (--group). - Commituj
uv.lock. Ignoruj.venvi stan cache. - Uruchamiaj narzędzia powiązane z projektem w środowisku projektu.
- W CI używaj
uv lock --checklub--locked. - Testuj każdy docelowy system operacyjny i architekturę, które obejmuje plik lock.
- Eksportuj formaty zgodności tylko dla konkretnych systemów, które ich potrzebują.
- Trzymaj dane uwierzytelniające indeksu poza commitowanymi plikami. Przekazuj je przez zmienne środowiskowe lub keyring.
Używam uv jako domyślnego narzędzia do Pythona na macOS, ponieważ jeden plik wykonywalny obsługuje te zadania i oddziela zależności projektów od zależności narzędzi.