亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

現(xiàn)代?Python?包管理器?uv的使用詳解

 更新時間:2025年06月11日 08:46:20   作者:wngtk  
uv的CLI規(guī)范和Go有點類似,尤其是go help和 uv help,uv 的任何命令有不理解的地方可以查看一下這個命令的 help,這篇文章主要介紹了現(xiàn)代Python包管理器uv,需要的朋友可以參考下

用 uv + Python 開發(fā)命令行工具

當(dāng)使用 uv 寫正規(guī)一點的 CLI 應(yīng)用的時候,還是應(yīng)該使用

uv init --package [package name]

因為寫一個命令行程序總是要安裝的,想分享到 PYPI 也必須要打包。

我都不知道我第一次用 uv 的時候是怎么正確打包,并能使用 uv 安裝我開發(fā)的程序。當(dāng)時真是誤打誤撞的,那時候我根本不知道 pyproject.toml 應(yīng)該怎么寫才能正確打包,更加不知道寫一個命令行程序的規(guī)范是什么。當(dāng)時我連 Build Backend 都沒有設(shè)置,純粹是運(yùn)氣好。

目錄結(jié)構(gòu)

一個 Python 應(yīng)用,不管是 CLI 工具,還是后端服務(wù),只要是一個想分發(fā)給別人用,項目都要有一個規(guī)范的目錄結(jié)構(gòu), flat-layout or src-layout?,F(xiàn)在比較流行 src-layout,如果沒有什么考量就使用 src-layout。

有固定的目錄結(jié)構(gòu)之后,一個包(文件夾)里面的__init__.py很重要,構(gòu)建系統(tǒng)默認(rèn)是只把有 __init__.py文件的文件夾才當(dāng)作是一個包。當(dāng)然 __init__.py 可以沒有,沒有 __init__.py 的包叫做 namespace package。要打包 namespace package 需要在 pyproject.toml里面給構(gòu)建系統(tǒng)指出怎么找到你的包。

Python 項目打包的細(xì)節(jié)我不太清楚,可以看看對應(yīng)的構(gòu)建后端的文檔,例如 hatch 的文檔。

uv 的使用

uv init

uv init 初始化一個項目

uv init example-app

默認(rèn)沒有使用 --lib, uv 就會使用 --app,相當(dāng)于

uv init --app example-app
$ tree example-app
example-app/
├── main.py
├── pyproject.toml
└── README.md

uv init 創(chuàng)建一個 Python 項目,自動建立好 pyproject.tomlREADME.md 等文件。在這里你可以隨意創(chuàng)建 .py 文件,也可以手動自己把代碼組織成 package。

運(yùn)行對應(yīng)的 py 文件,也稱為腳本。

uv run main.py

uv 不僅僅是一個包管理器,還可以說是 Python 構(gòu)建系統(tǒng)的前端,還是 Python 環(huán)境的管理器。

當(dāng)你想寫一個 Python 腳本做點事情,隨便在一個文件夾運(yùn)行 uv init 幫你創(chuàng)建好虛擬環(huán)境并管理依賴。運(yùn)行腳本就直接使用 uv run script.py。

uv init --package

如果是寫一個正經(jīng)的應(yīng)用,想分發(fā)一個包或者分發(fā)一個可執(zhí)行的命令,推薦使用 uv init --package。當(dāng)然也可以先用 uv init 起步,然后再自己手動創(chuàng)建包。

uv init --package

這相當(dāng)于 uv init --app --package。

uv 會使用 src-layout,把代碼放在 src/ 的 Python 包下,uv 會在 pyproject.toml 中添加一個 [project.scripts] entrypoint。

我們使用 uv init --package 創(chuàng)建一個 example-pkg,我們在這里使用了 --package。

~> uv init --package example-pkg
Initialized project `example-pkg` at `/home/user/example-pkg`
~> tree example-pkg/
example-pkg/
├── pyproject.toml
├── README.md
└── src
    └── example_pkg
        └── __init__.py
2 directories, 3 files
~> cd example-pkg/

--package 告訴 uv,我們希望用 Python 包來組織代碼。因為代碼放在 src/ 的文件夾里面,運(yùn)行起來不太方便。uv 在 pyproject.toml 中幫我們聲明了 [project.scripts]。

[project.scripts]
example-pkg = "example_pkg:main"

[project.scripts] 聲明了我們這個項目會有哪些命令,當(dāng)執(zhí)行這個 example-pkg 命令的時候調(diào)用對應(yīng)的函數(shù)。example_pkg:main 代表 example_pkg 這個包下的 main 函數(shù)。

See also:

創(chuàng)建一個項目后,為我們生成了一個命令叫做 example-pkg 要運(yùn)行這個 example-pkg 命令我們有兩個方式。

(1) 通過 uv run 來運(yùn)行我們的 example-pkg。

 ~/example-pkg (master)> uv run example-pkg
Using CPython 3.11.11 interpreter at: /usr/bin/python3.11
Creating virtual environment at: .venv
      Built example-pkg @ file:///home/user/example-pkg
Installed 1 package in 0.75ms
Hello from example-pkg!

(2) 可以激活 uv 給我們創(chuàng)建好的虛擬環(huán)境,再運(yùn)行我們的 example-pkg,我們就不需要通過 uv run 來運(yùn)行這個命令了。uv run 的解釋見下文。

~/example-pkg (master)> source .venv/bin/activate.fish
(example-pkg) ~/example-pkg (master)> example-pkg
Hello from example-pkg!

.venv 會在首次使用 uv run 自動創(chuàng)建。也可以使用 uv run 創(chuàng)建 venv 虛擬環(huán)境。uv sync 更新虛擬環(huán)境。

通??寺∠聞e人的項目后在項目的根目錄運(yùn)行 uv sync,uv 就會下載好需要的依賴并創(chuàng)建虛擬環(huán)境。

uv init --package 創(chuàng)建項目的時候 uv 給我們創(chuàng)建了一個和項目名字一樣的命令。

我們來加一個 hello-pkg 命令。

--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,6 +11,7 @@ dependencies = []
 [project.scripts]
 example-pkg = "example_pkg:main"
+hello-pkg = "example_pkg:main"
 [build-system]
 requires = ["hatchling"]

我們運(yùn)行 hello-pkg,uv 發(fā)現(xiàn) pyproject.toml 更新后自動重新安裝了我們的包。這個包會被安裝在 .venv。

~/example-pkg (master)> uv run hello-pkg
      Built example-pkg @ file:///home/user/example-pkg
Uninstalled 1 package in 0.81ms
Installed 1 package in 0.67ms
Hello from example-pkg!

如果你習(xí)慣在虛擬環(huán)境里面開發(fā),不想每次都運(yùn)行命令都要使用 uv run,更新 pyproject.toml 后要運(yùn)行一下 uv sync 更新當(dāng)前的虛擬環(huán)境。

這是你開發(fā)的命令程序,你可以把你的程序安裝用戶的全局。

uv tool install -e .

這樣就不必激活虛擬環(huán)境,也不必使用 uv run hello-pkg。

~> hello-pkg
Hello from example-pkg!

-e 代表 editable 安裝,意味著你改動代碼后是不需要重新安裝的。如果你更新了 pyproject.toml 或者其他的改動需要重新安裝,你可以運(yùn)行 uv tool upgrade example-pkg。

editable 安裝是 pip 也支持的命令,Python 3.6 就能用。

uv run

我的代碼可能放在 Python 包里,也可能是一個單獨的 .py 腳本,或者是一個腳本沒有任何文件擴(kuò)展名。

uv run 確保你運(yùn)行的命令/腳本是在一個 Python 的環(huán)境中。

當(dāng)你使用 uv init hello-uv-run 創(chuàng)建了一個項目。

~ $ uv init hello-uv-run
Initialized project `hello-uv-run` at `/home/user/hello-uv-run`
~ $ cd hello-uv-run/
~/hello-uv-run (master) $ eza -l
.rw-r--r--  90 user  9 Jun 23:04 main.py
.rw-r--r-- 158 user  9 Jun 23:04 pyproject.toml
.rw-r--r--   0 user  9 Jun 23:04 README.md

第一次使用 uv run,uv 創(chuàng)建了虛擬環(huán)境,uv 會確保你的 main.py 腳本是在創(chuàng)建的虛擬環(huán)境里面運(yùn)行的。這個時候我們的代碼就放在一個單獨的 .py 腳本文件里面。

$ uv run main.py
Using CPython 3.12.8 interpreter at: /usr/bin/python3.12
Creating virtual environment at: .venv
Hello from hello-uv-run!

我們給這個項目添加一個名為 typer 的依賴。演示一下如何使用庫提供的 CLI 工具。

~/hello-uv-run (master)> uv add typer
Resolved 10 packages in 13ms
Installed 8 packages in 17ms
 + click==8.2.1
 + markdown-it-py==3.0.0
 + mdurl==0.1.2
 + pygments==2.19.1
 + rich==14.0.0
 + shellingham==1.5.4
 + typer==0.16.0
 + typing-extensions==4.14.0

typer 提供了一個命令行程序 typer。 我們可以使用 typer 來運(yùn)行我們的 main.py 這個腳本。此時我們沒有激活 venv 虛擬環(huán)境,運(yùn)行 uv add 的 typer 命令,要使用 uv run typer。

~/hello-uv-run (master)> cat main.py
def main(name: str):
    print(f"Hello {name} from hello-uv-run!")
~/hello-uv-run (master)> uv run typer main.py run Joe
Hello Joe from hello-uv-run!

激活 venv 虛擬環(huán)境,就可以直接運(yùn)行 typer 命令。

(hello-uv-run) ~/hello-uv-run (master)> typer main.py run joe
Hello joe from hello-uv-run!

uv run 運(yùn)行一個命令或者腳本就和你激活虛擬環(huán)境后運(yùn)行命令或者腳本一樣。

有時候你需要給命令指定參數(shù),為了不讓 uv 誤以為參數(shù)是 uv run 的,你可以這樣:

uv run -- python -m src.example

這樣就 -m 就會正常傳遞給 python。如此常見的命令當(dāng)然 uv 有直接的支持,uv run -m 運(yùn)行一個 Python 模塊。

下面解釋一下前面的 typer 命令。typer 命令行程序的用處是:即便你只有一個 .py 腳本也能實現(xiàn)命令行的自動補(bǔ)全,腳本文件名通常不是一個命令的名字。typer --install-completion 安裝自動補(bǔ)全后,使用 typer main.py run 就能獲得命令行的自動補(bǔ)全。

下面這個例子來自 Typer 的官網(wǎng)。我們將代碼保存到 main.py。

import typer
app = typer.Typer()
@app.command()
def hello(name: str):
    print(f"Hello {name}")
@app.command()
def goodbye(name: str, formal: bool = False):
    if formal:
        print(f"Goodbye Ms. {name}. Have a good day.")
    else:
        print(f"Bye {name}!")
if __name__ == "__main__":
    app()

因為我們需要直接運(yùn)行 typer 命令才能獲得命令行的自動補(bǔ)全,我們有兩個辦法:(1) 使用 uv tool install typer 安裝 typer 到全局。(2) 激活 venv 虛擬環(huán)境,因為我們之前已經(jīng)使用 uv add typer 將 typer 安裝到了虛擬環(huán)境。

我們在 Shell 里面敲 typer main.py run 然后按 Tab 鍵就能得到命令行參數(shù)的補(bǔ)全了。

~/hello-uv-run (master)> typer main.py run
goodbye  hello

main.py 只是一個腳本,并不是一個包。一個腳本算不上是一個完整的應(yīng)用(或者項目),Python 被稱之為腳本語言,但 Python 能做的不僅僅是腳本,Python 能開發(fā)一個完整的應(yīng)用,JavaScript/Lua 也是。

單純的腳本,或許只有 Bash 這樣的才算吧。畢竟連 JavaScript 都有模塊,有構(gòu)建,有包(npm 包)。

我們可以通過 Shebang,chmod 賦予腳本可執(zhí)行權(quán)限,把腳本名字的 .py 后綴去掉,手動做到一個腳本看起來是一個獨立且完整的命令行程序。但是,這不是我們開發(fā) Python 命令行程序的方式,我們常規(guī)的方式是創(chuàng)建一個 Python 的包,使用 entry_point 機(jī)制提供命令行程序/GUI程序。uv init --package 就是一個示例。

我一直在強(qiáng)調(diào),你應(yīng)該用包把 Python 代碼組織起來??晌铱偛荒軐懭魏我粋€ Python 代碼都創(chuàng)建一個包吧。

比方說你可能想在你的 Python 項目里面寫一個小腳本,測試你的想法,試用一下某個庫,或者試試開發(fā)的包的某一個函數(shù)實現(xiàn)對不對,或者在代碼倉庫中給出使用你的 Python 包的 Python 腳本示例。

運(yùn)行你項目里的 .py 腳本你只需要使用 uv run script.py 就可以。

uv run 后面可以指定的是命令/腳本。如果你的腳本是 hello-uv-run/main.py 你只需要 uv run main.py。如果你的腳本的后綴不是 .py,是沒有后綴的。你可以加一個 --script 選項。

uv run --script main

uv run 能自動更新虛擬環(huán)境,uv run 能知道你項目的可執(zhí)行腳本([project.scripts]),uv run 也能幫你運(yùn)行你不想放在包里面的腳本,哪怕你不想命名腳本為 .py 結(jié)尾的文件。uv 幫你處理好環(huán)境問題,你不需要提前激活虛擬環(huán)境,也不需要提前把你開發(fā)的包安裝到虛擬環(huán)境,只要你使用 uv run 來啟動你寫的腳本/命令就能找到它應(yīng)該找到的包。

不要忘了前面提到的方法,你還可以這樣來指定運(yùn)行 Python 腳本時給 Python 的選項。例如:

uv run -- python -i main.py

還是那句話,你想要代碼被分發(fā),你就要把代碼放在一個包里面,有 __init__.py 的文件夾才是 Python 的包。如果一個文件夾里面沒有 __init__.py,打包的時候,這個文件夾下的代碼就不會被打包,文件夾名字對應(yīng)的 Python 包也不存在。

如果你的包要提供一個可執(zhí)行的腳本,就在 [project.scripts] 里面聲明一個命令,這個命令對應(yīng)的是包下的某一個模塊的某一個函數(shù)。這似乎是唯一的方式。之前的那種在包之外創(chuàng)建一個腳本調(diào)用包是過時的做法。不管你是使用 setup.py 還是 pyproject.toml,現(xiàn)在推薦的做法都是聲明一個 entry_points。

我問了 DeepSeek,為什么現(xiàn)在的 pyproject.toml 不支持單獨寫一個腳本作為命令執(zhí)行的入口。下面是它的回答。

現(xiàn)代 Python 項目更傾向于使用 entry_points 和包內(nèi) CLI 代碼,因其在兼容性、維護(hù)性和工具鏈支持上的顯著優(yōu)勢。

通過 setup.py 或 pyproject.toml 的 entry_points 機(jī)制,可以直接將包內(nèi)的函數(shù)注冊為命令行工具,無需單獨維護(hù)腳本文件。

一些老的 setup.py 里面會看到 setup 傳一個 scripts 參數(shù),指定一個單獨的 python 腳本作為命令行程序的入口,這在現(xiàn)代 python 是不推薦的做法。

TIPS:

開發(fā)的時候希望從環(huán)境變量讀取 API KEY 或者數(shù)據(jù)庫的連接地址和密碼。創(chuàng)建一個 .env 文件,uv run 支持從指定文件讀取環(huán)境變量。

uv run --env-file .env main.py

如果你使用的是 Fish shell,你可以通過環(huán)境變量設(shè)置 uv 默認(rèn)的 ENV_FILE。

set -Ux UV_ENV_FILE .env

uv tool

如果你只想臨時運(yùn)行一個由 Python 包提供的命令,你可以使用

uv tool run

uv tool run 是臨時安裝命令到一個隔離的環(huán)境中。uv tool install 可以取代 pipx

如果你不想激活虛擬環(huán)境也不想切換你的工作目錄,你就想運(yùn)行一下本地計算機(jī)上你開發(fā)的某個 Python 包提供命令。

uv tool run --from <package path> package-command

是的,這非常有用,尤其是你想運(yùn)行一個命令,但是又不想安裝它。不管這個命令從網(wǎng)上能下載到的,還是在你本地計算機(jī)上暫時不安裝到全局的。

如果你要使用 pip 這個包管理器安裝 cmake/meson,你不應(yīng)該使用系統(tǒng)自帶的 pip,因為這會污染系統(tǒng)的 Python 環(huán)境,安裝一個獨立的應(yīng)用,應(yīng)該使用 pipx 而不是 pip。不過現(xiàn)在有 uv 這樣的工具,估計也不太會再使用 pipx 了。

你開發(fā)的命令行工具可以直接使用 uv tool install 安裝,只需指定 git 的 clone 地址。

uv tool install

uv workspace

創(chuàng)建一個 pyproject.toml 表示這個目錄是一個 Python 項目。

$ uv init --bare example
Initialized project `example`

在 example 目錄下創(chuàng)建新的 uv 項目都會自動更新 example/pyproject.toml, 一個項目依賴 workspace 的其他項目可以直接使用 uv add projectname 添加,就像這個項目已經(jīng)放在 PYPI 上一樣。

總結(jié)

uv 的 CLI 規(guī)范和 Go 有點類似,尤其是 go help 和 uv help。uv 的任何命令有不理解的地方可以查看一下這個命令的 help。

如果希望有一個命令行命令,所有 CLI 邏輯應(yīng)放在包的模塊內(nèi)(如 src/example_pkg/cli.py),通過 __init__.py 定義包,而非分散的腳本文件。或者所有的 CLI 邏輯單獨放在一個包里面(如 src/cli/__init__.py)。

uv run? 自動處理虛擬環(huán)境,直接運(yùn)行腳本或命令。你可以把代碼放在包里,也可以不放在包里。

  • uv run script.py 運(yùn)行項目里面的腳本,script.py 在 src/ 之外。
  • uv run --script myscript 運(yùn)行項目里面的腳本沒有 .py 后綴
  • uv run -- python -m mymodule 運(yùn)行虛擬環(huán)境的 python 使用 -m 選項,將模塊作為腳本運(yùn)行
  • uv run console-script 運(yùn)行在 [project.scripts] 中聲明的 console-script

如果你激活了虛擬環(huán)境,你就可以把 uv run 去掉了。如果你使用 uv tool 安裝 Python 包,就可以不激活運(yùn)行 console-script

舊版 setup.py 中通過 scripts=["scripts/myscript.py"] 的方式已被淘汰。

你想要代碼被分發(fā),你就要把代碼放在一個包里面,有 __init__.py 的文件夾才是 Python 的包。

本文就先寫到這里了,有了這些知識后相信你已經(jīng)知道如何在用 Python 開發(fā)應(yīng)用/庫的過程使用 uv 了。尤其是強(qiáng)大的 uv run 讓你的代碼隨意組織,又能方便運(yùn)行。在使用 uv 的項目中,你可以又腳本,也可以有包,可以將一個腳本慢慢變成包。uv 一定會成為你 Python 開發(fā)過程中一件趁手的工具。

到此這篇關(guān)于現(xiàn)代 Python 包管理器 uv的文章就介紹到這了,更多相關(guān)現(xiàn)代 Python 包管理器 uv內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python?@property?裝飾器使用方法

    python?@property?裝飾器使用方法

    這篇文章主要介紹了python?@property?裝飾器使用詳細(xì),使用property可以講類的方法變成同名屬性,使用起來更加簡潔,下文最后舉例說明詳情說明需要的小伙伴可以參考一下
    2022-03-03
  • python pcm音頻添加頭轉(zhuǎn)成Wav格式文件的方法

    python pcm音頻添加頭轉(zhuǎn)成Wav格式文件的方法

    今天小編就為大家分享一篇python pcm音頻添加頭轉(zhuǎn)成Wav格式文件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01
  • 使用python爬取taptap網(wǎng)站游戲截圖的步驟

    使用python爬取taptap網(wǎng)站游戲截圖的步驟

    這篇文章主要介紹了使用python爬取taptap游戲截圖的步驟,幫助大家更好的理解和學(xué)習(xí)使用python進(jìn)行爬蟲,感興趣的朋友可以了解下
    2021-05-05
  • python的scipy.stats模塊中正態(tài)分布常用函數(shù)總結(jié)

    python的scipy.stats模塊中正態(tài)分布常用函數(shù)總結(jié)

    在本篇內(nèi)容里小編給大家整理的是一篇關(guān)于python的scipy.stats模塊中正態(tài)分布常用函數(shù)總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-02-02
  • Sklearn調(diào)優(yōu)之網(wǎng)格搜索與隨機(jī)搜索原理詳細(xì)分析

    Sklearn調(diào)優(yōu)之網(wǎng)格搜索與隨機(jī)搜索原理詳細(xì)分析

    這篇文章主要介紹了Sklearn調(diào)優(yōu)之網(wǎng)格搜索與隨機(jī)搜索原理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • Python使用Opencv實現(xiàn)圖像特征檢測與匹配的方法

    Python使用Opencv實現(xiàn)圖像特征檢測與匹配的方法

    這篇文章主要介紹了Python使用Opencv實現(xiàn)圖像特征檢測與匹配的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Django url反向解析的實現(xiàn)

    Django url反向解析的實現(xiàn)

    本文主要介紹了Django url反向解析的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • 解決Django模板無法使用perms變量問題的方法

    解決Django模板無法使用perms變量問題的方法

    這篇文章主要給大家介紹了關(guān)于解決Django模板無法使用perms變量問題的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-09-09
  • python繪制橫豎條形圖的方法

    python繪制橫豎條形圖的方法

    這篇文章主要為大家詳細(xì)介紹了python繪制橫豎條形圖的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • python中pip無法正確安裝或路徑出錯的解決方案

    python中pip無法正確安裝或路徑出錯的解決方案

    這篇文章主要介紹了python中pip無法正確安裝或路徑出錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論