Python包管理不再头疼:uv工具快速上手
<p><code>Python</code> 包管理生态中存在多种工具,如 <code>pip</code>、<code>pip-tools</code>、<code>poetry</code>、<code>conda</code> 等,各自具备一定功能。</p><p>而今天介绍的<code>uv</code> 是 <code>Astral</code> 公司推出的一款基于 <code>Rust</code> 编写的 <code>Python</code> 包管理工具,旨在成为 “<strong>Python 的 Cargo</strong>”。</p>
<p>它提供了快速、可靠且易用的包管理体验,在性能、兼容性和功能上都有出色表现,为 <code>Python</code> 项目的开发和管理带来了新的选择。</p>
<h1 id="1-为什么用uv">1. 为什么用uv</h1>
<p>与其他<code>Python</code>中的包管理工具相比,<code>uv</code>更像是一个全能选手,它的优势在于:</p>
<ol>
<li><strong>速度快</strong>:得益于<code>Rust</code>,<code>uv</code>工具的速度让人惊艳,比如安装依赖,速度比其他工具快很多</li>
<li><strong>功能全面</strong>:<code>uv</code> 是“<strong>一站式服务</strong>”的工具,从安装 Python、管理虚拟环境,到安装和管理包,再到管理项目依赖,它统统都能处理得很好</li>
<li><strong>前景光明</strong>:背后有风投公司<code>Astral</code>支持,且采用了<code>MIT</code>许可,即使未来出现问题,社区也有应对的办法</li>
</ol>
<p>使用<code>uv</code>,也可以像<code>NodeJS</code>或者<code>Rust</code>项目那样方便的管理依赖。</p>
<h1 id="2-如何安装">2. 如何安装</h1>
<p>安装 <code>uv</code> 非常简单,可以使用官方提供的安装脚本,也可以通过<code>pip</code>来安装。</p>
<pre><code class="language-bash"># On macOS and Linux.
curl -LsSf https://astral.sh/uv/install.sh | sh
# On Windows.
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# With pip.
pip install uv
</code></pre>
<p>安装之后,可以通过<code>uv help</code>命令检查是否安装成功:</p>
<p><img src="https://img2024.cnblogs.com/blog/83005/202412/83005-20241227125034737-1020856408.png" alt="" loading="lazy"></p>
<h1 id="3-如何使用">3. 如何使用</h1>
<p>下面演示如何使用<code>uv</code>来管理<code>Python</code>项目。</p>
<p>使用<code>uv</code>之前,创建一个<code>Python</code>项目对我来说就是创建一个文件夹而已。</p>
<p>使用<code>uv</code>之后,终于有了一些项目的感觉,对于<code>uv</code>,我使用时间也不长,疏漏或错误的地方欢迎指正!</p>
<p>接下来,从创建一个项目开始,演示我使用<code>uv</code>时常用的一些功能。</p>
<p>首先,介绍<code>uv</code>工具主要使用的两个文件:</p>
<ul>
<li><code>pyproject.toml</code>:定义项目的主要依赖,包括项目名称、版本、描述、支持的 <code>Python</code> 版本等信息</li>
<li><code>uv.lock</code>:记录项目的所有依赖,包括依赖的依赖,且跨平台,确保在不同环境下安装的一致性。这个文件由 <code>uv</code> 自动管理,不要手动编辑</li>
</ul>
<h2 id="31-创建项目">3.1. 创建项目</h2>
<p>接下来,创建一个项目,使用<code>uv init <project dir></code>命令。</p>
<pre><code class="language-bash">$uv init myproject
Initialized project `myproject` at `D:\projects\python\myproject`
$cd .\myproject\
$ls
目录: D:\projects\python\myproject
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2024/12/2712:06:08 109 .gitignore
-a---- 2024/12/2712:06:08 5 .python-version
-a---- 2024/12/2712:06:08 87 hello.py
-a---- 2024/12/2712:06:08 155 pyproject.toml
-a---- 2024/12/2712:06:08 0 README.md
</code></pre>
<p>通过<code>init</code>创建项目之后,<code>uv</code>工具贴心地帮助我们生成了一些默认文件。</p>
<p>其中 <code>hello.py</code> 只是一段演示用的代码,</p>
<p>随后我们可以根据实际的项目需要删除这个代码文件,换成自己的实际代码。</p>
<pre><code class="language-bash">$cat .\hello.py
def main():
print("Hello from myproject!")
if __name__ == "__main__":
main()
</code></pre>
<p><code>pyproject.toml</code>中是一些项目信息:</p>
<pre><code class="language-bash">$cat .\pyproject.toml
name = "myproject"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
</code></pre>
<p><strong>注意</strong>,<code>uv init</code> 创建项目之后,会自动将项目使用<code>Git</code>来管理。</p>
<h2 id="32-操作环境">3.2. 操作环境</h2>
<p>创建项目之后,我们进入项目根文件夹的第一件事就是同步项目依赖。</p>
<pre><code class="language-bash">$uv sync
Using CPython 3.12.4 interpreter at: D:\miniconda3\envs\databook\python.exe
Creating virtual environment at: .venv
Resolved 1 package in 15ms
Audited in 0.05ms
</code></pre>
<p>同步之后,会自动查找或下载合适的 <code>Python</code> 版本,创建并设置项目的虚拟环境,构建完整的依赖列表并写入</p>
<p><code>uv.lock</code> 文件,最后将依赖同步到虚拟环境中。</p>
<p>我们这个是新创建的项目,没有什么依赖,所以<code>uv.lock</code> 文件中的内容也比较简单。</p>
<pre><code class="language-bash">$ls
目录: D:\projects\python\myproject
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2024/12/2712:12:39 .venv
-a---- 2024/12/2712:06:08 109 .gitignore
-a---- 2024/12/2712:06:08 5 .python-version
-a---- 2024/12/2712:06:08 87 hello.py
-a---- 2024/12/2712:06:08 155 pyproject.toml
-a---- 2024/12/2712:06:08 0 README.md
-a---- 2024/12/2712:12:39 116 uv.lock
$cat .\uv.lock
version = 1
requires-python = ">=3.12"
[]
name = "myproject"
version = "0.1.0"
source = { virtual = "." }
</code></pre>
<p><code>uv sync</code>同步之后,就可以运行项目的代码了。</p>
<p>既然使用<code>uv</code>管理项目的话,我们就使用<code>uv</code>的命令来运行代码,不要像以前那样使用<code>python xxx.py</code>来运行。</p>
<p>我们可以试着运行项目创建时自动生成的代码。</p>
<pre><code class="language-bash">$uv run .\hello.py
Hello from myproject!
</code></pre>
<h2 id="33-管理依赖">3.3. 管理依赖</h2>
<p>管理依赖是我使用<code>uv</code>工具的主要目的,使用<code>uv</code>添加依赖非常简单,和<code>npm</code>和<code>cargo</code>差不多。</p>
<pre><code class="language-bash">$uv add pandas
Resolved 7 packages in 3.41s
Prepared 6 packages in 4.63s
Installed 6 packages in 1.80s
+ numpy==2.2.1
+ pandas==2.2.3
+ python-dateutil==2.9.0.post0
+ pytz==2024.2
+ six==1.17.0
+ tzdata==2024.2
</code></pre>
<p>尝试安装了一个<code>pandas</code>依赖(pandas依赖的包也自动安装了),从上面日志可以看出速度非常快。</p>
<p>这时再看看<code>uv.lock</code> 文件的变化。</p>
<pre><code class="language-bash">$cat .\uv.lock
version = 1
requires-python = ">=3.12"
[]
name = "myproject"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pandas" },
]
requires-dist = [{ name = "pandas", specifier = ">=2.2.3" }]
[]
name = "pandas"
version = "2.2.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "numpy" },
{ name = "python-dateutil" },
{ name = "pytz" },
{ name = "tzdata" },
]
[]
name = "pytz"
version = "2024.2"
source = { registry = "https://pypi.org/simple" }
</code></pre>
<p>上面的日志中我删除了很多内容,因为整体内容太多,详细记录了每个包以及它依赖的包的情况。</p>
<p><code>uv.lock</code>这个文件我们不要手动去编辑它,使用<code>uv</code>工具去管理它。</p>
<p>引入了pandas之后,我们看看是否可以在<code>hello.py</code>中使用。</p>
<pre><code class="language-bash">$cat .\hello.py
import pandas as pd
def main():
print("Hello from myproject!")
df = pd.DataFrame(
{
"A": ,
"B": ,
}
)
print(df)
if __name__ == "__main__":
main()
$uv run .\hello.py
Hello from myproject!
AB
014
125
236
</code></pre>
<p>可以正常使用安装的包<code>pandas</code>,下面在试试删除依赖会怎么样。</p>
<pre><code class="language-bash">$uv remove pandas
Resolved 1 package in 12ms
Uninstalled 6 packages in 1.18s
- numpy==2.2.1
- pandas==2.2.3
- python-dateutil==2.9.0.post0
- pytz==2024.2
- six==1.17.0
- tzdata==2024.2
$cat .\uv.lock
version = 1
requires-python = ">=3.12"
[]
name = "myproject"
version = "0.1.0"
source = { virtual = "." }
</code></pre>
<p>使用<code>uv remove</code>命令删除<code>pandas</code>包之后,也会自动删除<code>pandas</code>依赖的其他包,</p>
<p>我们看到<code>uv.lock</code> 文件也恢复到最初的内容。</p>
<p>再试试运行<code>hello.py</code>看看。</p>
<pre><code class="language-bash">$uv run .\hello.py
Traceback (most recent call last):
File "D:\projects\python\myproject\hello.py", line 1, in <module>
import pandas as pd
ModuleNotFoundError: No module named 'pandas'
</code></pre>
<p>果然,无法运行了。</p>
<h2 id="34-区分开发和生产环境">3.4. 区分开发和生产环境</h2>
<p>还有一个比较常用的功能是区分<strong>开发环境</strong>和<strong>生产环境</strong>的依赖,这个功能在<code>NodeJS</code>和<code>Rust</code>中很常见。</p>
<p>比如,我们想把<code>pandas</code>安装到开发环境中,而把<code>requests</code>安装到生产环境中。</p>
<pre><code class="language-bash">$uv add --group dev pandas
Resolved 7 packages in 1.72s
Installed 6 packages in 1.39s
+ numpy==2.2.1
+ pandas==2.2.3
+ python-dateutil==2.9.0.post0
+ pytz==2024.2
+ six==1.17.0
+ tzdata==2024.2
$uv add --group production requests
Resolved 12 packages in 2.72s
Prepared 5 packages in 1.31s
Installed 5 packages in 68ms
+ certifi==2024.12.14
+ charset-normalizer==3.4.1
+ idna==3.10
+ requests==2.32.3
+ urllib3==2.3.0
</code></pre>
<p>安装之后,<code>uv.lock</code> 文件自动添加了各个包及其依赖,这里不再赘述。</p>
<p>从项目的<code>pyproject.toml</code>中可以看出不同环境的包依赖。</p>
<pre><code class="language-bash">$cat .\pyproject.toml
name = "myproject"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = []
dev = [
"pandas>=2.2.3",
]
production = [
"requests>=2.32.3",
]
</code></pre>
<h1 id="4-未来发展">4. 未来发展</h1>
<p><code>uv</code> 也可以构建和发布 <code>Python</code> 包到 <code>PyPi</code>,具体细节本篇就不展开了。</p>
<p><code>uv</code> 自从发布后,团队一直致力于优先提升其跨平台的兼容性、性能和稳定性,帮助用户顺利将项目过渡到使用<code>uv</code>来管理。</p>
<p>长远来看,<code>uv</code> 将发展成为一个完整的 <code>Python</code> 项目和包管理器,提供一站式的开发体验,涵盖从 <code>Python</code> 安装到项目管理的各个环节,进一步简化 <code>Python</code> 项目的开发流程,提高开发效率。</p><br><br>
来源:https://www.cnblogs.com/wang_yb/p/18635441
頁:
[1]