使用 uv 管理 Python 环境

2025-06-04

使用 uv 管理 Python 环境

要管理Python环境,你可以使用多种工具完成,如果使用pyenv来安装不同版本的Python、venv或者pipenv管理虚拟环境、诗歌管理专案,这些工具都可以单独做好,不过使用起来就是分开的工具,而uv则提供单一工具来完成上述所有工作,而且速度快、简单易用。

安装紫外线

uv本身并不需要 Python,所以不建议用 pip 或者 pipx 安装,这样都会跟特定的 Python 环境绑在一起,Windows 上就直接透过 PowerSehll 安装即可:

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Enter fullscreen mode Exit fullscreen mode

或者透过勺子等软件管理工具安装:

scoop install uv
Enter fullscreen mode Exit fullscreen mode

本文均以 Windows 平台在 PowerShell 下操作示范,如果是其他平台,请自行替换成对应的指令。

使用 uv 管理多版本 Python

使用uv python list可以显示可安装以及已安装的Python版本:

# uv python list
cpython-3.13.1+freethreaded-windows-x86_64-none    <download available>
cpython-3.13.1-windows-x86_64-none                 <download available>
cpython-3.12.8-windows-x86_64-none                 <download available>
cpython-3.11.11-windows-x86_64-none                <download available>
cpython-3.10.16-windows-x86_64-none                <download available>
cpython-3.9.21-windows-x86_64-none                 <download available>
cpython-3.8.20-windows-x86_64-none                 <download available>
cpython-3.7.9-windows-x86_64-none                  <download available>
pypy-3.10.14-windows-x86_64-none                   <download available>
pypy-3.9.19-windows-x86_64-none                    <download available>
pypy-3.8.16-windows-x86_64-none                    <download available>
pypy-3.7.13-windows-x86_64-none                    <download available>
Enter fullscreen mode Exit fullscreen mode

如果要安装最新版本,可以使用uv python install

# uv python install
Installed Python 3.13.1 in 5.89s
 + cpython-3.13.1-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

查看安装结果:

# uv python list
cpython-3.13.1+freethreaded-windows-x86_64-none    <download available>
cpython-3.13.1-windows-x86_64-none                 C:\Users\meebo\AppData\Roaming\uv\python\cpython-3.13.1-windows-x86_64-none\python.exe
cpython-3.12.8-windows-x86_64-none                 <download available>
cpython-3.11.11-windows-x86_64-none                <download available>
cpython-3.10.16-windows-x86_64-none                <download available>
cpython-3.9.21-windows-x86_64-none                 <download available>
cpython-3.8.20-windows-x86_64-none                 <download available>
cpython-3.7.9-windows-x86_64-none                  <download available>
pypy-3.10.14-windows-x86_64-none                   <download available>
pypy-3.9.19-windows-x86_64-none                    <download available>
pypy-3.8.16-windows-x86_64-none                    <download available>
pypy-3.7.13-windows-x86_64-none                    <download available>
Enter fullscreen mode Exit fullscreen mode

安装版本会显示安装路径。已你也可以通过uv python dir指令找到Python的安装路径:

# uv python dir
C:\Users\meebo\AppData\Roaming\uv\python
Enter fullscreen mode Exit fullscreen mode

如果已经安装过Python,除非额外指定版本,否则就无法安装:

# uv python install
Python is already installed. Use `uv python install <request>` to install another version.
Enter fullscreen mode Exit fullscreen mode

指定安装特定的版本:

# uv python install 3.10
Installed Python 3.10.16 in 9.78s
 + cpython-3.10.16-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

它会自行寻找符合的版本。

要删除已经安装的Python,必须使用uv python uninstall

# uv python uninstall 3.10
Searching for Python versions matching: Python 3.10
Uninstalled Python 3.10.16 in 1.52s
 - cpython-3.10.16-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

删除时一定要指定版本,它同样会搜索相同的版本。

使用uv python list时列出次版本号的最新修订版本,例如 3.10.16,如果希望所有的版本修订,可以加上--all-versions选项,实际上你也可以只安装同一个版本号的其他修订版本,例如:

# uv python install 3.10.8
Installed Python 3.10.8 in 7.59s
 + cpython-3.10.8-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

如果简单指定次版本号删除Python,即可删除所有与该次版本号一致的修订版本,例如:

# uv python uninstall 3.10
Searching for Python versions matching: Python 3.10
Uninstalled 2 versions in 1.02s
 - cpython-3.10.8-windows-x86_64-none
 - cpython-3.10.16-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

安装Python时也可以同时指定多个版本:

# uv python install 3.10 3.11
Installed 2 versions in 8.71s
 + cpython-3.10.16-windows-x86_64-none
 + cpython-3.11.11-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

移除时也一样:

# uv python uninstall 3.10 3.11
Searching for Python versions matching: Python 3.10
Searching for Python versions matching: Python 3.11
Uninstalled 2 versions in 2.67s
 - cpython-3.10.16-windows-x86_64-none
 - cpython-3.11.11-windows-x86_64-none
Enter fullscreen mode Exit fullscreen mode

使用 uv 替代 python/pip 工具

要注意的是,uv 管理的 Python 环境并不能直接透过python指令执行必须,透过 uv 来执行。以底下这个 Python 程序为例:

# cat .\show_version.py
import sys
print(sys.version)
Enter fullscreen mode Exit fullscreen mode

如果要刚刚通过 uv 安装的 Python 执行,指令为uv run

# uv run .\show_version.py
3.13.1 (main, Dec 19 2024, 14:38:48) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

uv 会找到它所可以的Python环境来执行,基本上的顺序如下:

  1. 目前资料夹下的.python-version档内设定的版本。
  2. 目前启用的虚拟环境。
  3. 目前数据夹下的.venv 数据夹内设定的虚拟环境。
  4. uv自己安装的Python。
  5. 系统环境变量设置Python环境。

你也可以在执行时--python跨越引数指定Python版本:

# uv run --python 3.10 .\show_version.py
3.10.16 (main, Dec 19 2024, 14:31:40) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

如果指定的版本不存在,uv会自动安装一致的Python,因此你可以看到上述例子,虽然之前删除了3.10版本,但仍然可以执行。

你也可以从标准输入直接送入执行,例如:

# echo 'print("hello world!")' | uv run -
hello world!
Enter fullscreen mode Exit fullscreen mode

如果安装了多个Python版本,uv默认会选择最新的版本,你可以通过uv python list --only-installed查看已安装的版本:

# uv python list --only-installed
cpython-3.13.1-windows-x86_64-none     C:\Users\meebo\AppData\Roaming\uv\python\cpython-3.13.1-windows-x86_64-none\python.exe
cpython-3.10.16-windows-x86_64-none    C:\Users\meebo\AppData\Roaming\uv\python\cpython-3.10.16-windows-x86_64-none\python.exe
Enter fullscreen mode Exit fullscreen mode

如果程序没有指定版本,执行Python时可以使用比较新的3.13:

# uv run .\show_version.py
3.13.1 (main, Dec 19 2024, 14:38:48) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

如果想要设置uv默认使用的Python版本,可以使用uv python pin,例如:

# uv python pin 3.10
Pinned `.python-version` to `3.10`
Enter fullscreen mode Exit fullscreen mode

设置程序之后,如果再次执行Python,就会改用刚才指定的版本:

# uv run .\show_version.py
3.10.16 (main, Dec 19 2024, 14:31:40) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

这个设置实际上会在当前数据夹下创建一个 .python-version 文件,并在其中记录指定的版本:

# cat .\.python-version
3.10
Enter fullscreen mode Exit fullscreen mode

这个文件只对所在的资料夹有效,如果离开这个资料夹,就没有效果了。uv 并没有提供取消指定默认版本的指令,如果要取消,就只要把 .python-version 文件删除:

# rm .\.python-version
# uv run .\show_version.py
3.13.1 (main, Dec 19 2024, 14:38:48) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

指定执行时需要的套件

如果您的程序需要其他套件才能执行,例如以下使用cowsay套件的程序:

# cat .\cow.py
from cowsay import cow
cow('hello, world')
Enter fullscreen mode Exit fullscreen mode

直接执行当然不行:

# uv run .\cow.py
Traceback (most recent call last):
  File "C:\Users\meebo\code\python\test\cow.py", line 1, in <module>
    from cowsay import cow
ModuleNotFoundError: No module named 'cowsay'
Enter fullscreen mode Exit fullscreen mode

uv 提供了便捷的方式,您可以利用--with选项指定套件:

# uv run --with cowsay .\cow.py
Installed 1 package in 13ms
  ____________
| hello, world |
  ============
            \
             \
               ^__^
               (oo)\_______
               (__)\       )\/\
                   ||----w |
                   ||     ||
Enter fullscreen mode Exit fullscreen mode

uv 会建立一个临时的虚拟环境,即时下载安装指定的套件:

如果想知道这个虚拟环境建置在哪里,可以据悉uv cache dir

# uv cache dir
C:\Users\meebo\AppData\Local\uv\cache
Enter fullscreen mode Exit fullscreen mode

--with指定套件时将以一致的虚拟环境执行,如果只是简单执行程序,没有使用--with选项,仍然会找不到套件:

# uv run .\cow.py
Traceback (most recent call last):
  File "C:\Users\meebo\code\python\test\cow.py", line 1, in <module>
    from cowsay import cow
ModuleNotFoundError: No module named 'cowsay'
Enter fullscreen mode Exit fullscreen mode

虚拟环境会和指定的套件捆绑在一起,如果执行使用相同套件的程序,例如:

# cat cow2.py
from cowsay import cow
cow('Hello, Python')
Enter fullscreen mode Exit fullscreen mode

就会沿着已经建立的虚拟环境,不会重新安装套件:

# uv run --with cowsay .\cow2.py
  _____________
| Hello, Python |
  =============
             \
              \
                ^__^
                (oo)\_______
                (__)\       )\/\
                    ||----w |
                    ||     ||
Enter fullscreen mode Exit fullscreen mode

你也可以使用uv cache clean临时建立的虚拟环境来清除:

# uv cache clean
Clearing cache at: C:\Users\meebo\AppData\Local\uv\cache
Removed 1166 files (13.2MiB)
Enter fullscreen mode Exit fullscreen mode

这时若程序再重新执行特定需要套件的,就会重新建立虚拟环境,并且安装套件:

# uv run --with cowsay .\cow.py
Installed 1 package in 13ms
  ____________
| hello, world |
  ============
            \
             \
               ^__^
               (oo)\_______
               (__)\       )\/\
                   ||----w |
                   ||     ||
Enter fullscreen mode Exit fullscreen mode

如果需要多个套件,例如以下这个同时需要cowsay和rich套件的程序:

# cat .\cow_rich.py
from cowsay import cow
cow('hello, rich')

from rich import print
print('hello, cow')
Enter fullscreen mode Exit fullscreen mode

执行时就可以用逗号隔开指定需要的套件:

# uv run --with cowsay,rich .\cow_rich.py
Installed 5 packages in 112ms
  ___________
| hello, rich |
  ===========
           \
            \
              ^__^
              (oo)\_______
              (__)\       )\/\
                  ||----w |
                  ||     ||
hello, cow
Enter fullscreen mode Exit fullscreen mode

或者也可以重复使用--with选项:

# uv run --with cowsay --with rich .\cow_rich.py
Installed 5 packages in 90ms
  ___________
| hello, rich |
  ===========
           \
            \
              ^__^
              (oo)\_______
              (__)\       )\/\
                  ||----w |
                  ||     ||
hello, cow
Enter fullscreen mode Exit fullscreen mode

你也可以同时指定套件的版本(由于<是转向的符号,为避免 PowerShell 解译错误,记住加上备用的单引号将套件名称与版本条件包起来):

# uv run --with 'cowsay>6,<7,rich' .\cow_rich.py
  ___________
| hello, rich |
  ===========
           \
            \
              ^__^
              (oo)\_______
              (__)\       )\/\
                  ||----w |
                  ||     ||
hello, cow
Enter fullscreen mode Exit fullscreen mode

最后再清理临时建立的虚拟环境:

# uv cache clean
Clearing cache at: C:\Users\meebo\AppData\Local\uv\cache
Removed 1202 files (13.5MiB)
Enter fullscreen mode Exit fullscreen mode

管理虚拟环境

使用--with虽然很方便,但是如果没有解密处理,可能会积累一大堆临时的虚拟环境因此,最好还是针对自己的需求创建虚拟环境。uv提供有uv venv指令可以创建虚拟环境,首先将当前数据夹下的.venv资料夹中创建的虚拟环境,例如底下以指定3.10版本的Python创建虚拟环境:

# uv venv --python 3.10
Using CPython 3.10.16
Creating virtual environment at: .venv
Activate with: .venv\Scripts\activate
Enter fullscreen mode Exit fullscreen mode

创建完成后如果执行Python程序,就会自动以当前数据夹中的虚拟环境执行:

# uv run .\show_version.py
3.10.16 (main, Dec 19 2024, 14:31:40) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

你也可以指定虚拟环境的数据夹名称,例如底下建立3.13版本的虚拟环境:

# uv venv p313
Using CPython 3.13.1
Creating virtual environment at: p313
Activate with: p313\Scripts\activate
Enter fullscreen mode Exit fullscreen mode

uv 默认并不会采用名称不是 .venv 的虚拟环境,您可以使用--python指定要使用的虚拟环境:

# uv run --python p313 .\show_version.py
3.13.1 (main, Dec 19 2024, 14:38:48) [MSC v.1942 64 bit (AMD64)]
Enter fullscreen mode Exit fullscreen mode

如果要删除虚拟环境,只要把虚拟环境的数据夹删除即可:

# rm -r -fo .\p313\
Enter fullscreen mode Exit fullscreen mode

管理套件

uv 提供有uv pip指令,能够让你使用跟pip相内容的介面管理套件,uv pip会依循uv run的方式找到 Python 执行环境,因此,若当前数据夹有 .venv 虚拟环境,操作的对象就是虚拟环境,或者也可以使用--python指定环境执行。

例如,我们可以在刚刚建立的虚拟环境中安装cowsay套件:

# uv pip install cowsay
Resolved 1 package in 302ms
Installed 1 package in 70ms
 + cowsay==6.1
Enter fullscreen mode Exit fullscreen mode

就可以执行前面看过的cow.py:

# uv run .\cow.py
  ____________
| hello, world |
  ============
            \
             \
               ^__^
               (oo)\_______
               (__)\       )\/\
                   ||----w |
                   ||     ||
Enter fullscreen mode Exit fullscreen mode

要注意的是,uv pip维持与pip的一致性,由于没有额外的相依关系可以参考,所以删除套件依赖信息时并不意味着不再需要的套件也一并删除。例如以下先安装需要依赖其他套件的丰富:

# uv pip install rich
Resolved 5 packages in 369ms
Prepared 1 package in 61ms
Installed 5 packages in 146ms
 + markdown-it-py==3.0.0
 + mdurl==0.1.2
 + pygments==2.19.1
 + rich==13.9.4
 + typing-extensions==4.12.2
Enter fullscreen mode Exit fullscreen mode

我们可以使用uv pip tree指令来查看目前的套件依赖关系:

# uv pip tree
cowsay v6.1
rich v13.9.4
├── markdown-it-py v3.0.0
│   └── mdurl v0.1.2
├── pygments v2.19.1
└── typing-extensions v4.12.2
Enter fullscreen mode Exit fullscreen mode

你可以看到 rich 直接依赖三个套件,其中一个套件又会依赖另一个套件,如果我们删除 rich 套件:

# uv pip uninstall rich
Uninstalled 1 package in 27ms
 - rich==13.9.4
Enter fullscreen mode Exit fullscreen mode

重新重新观察目前的依赖关系:

# uv pip tree
cowsay v6.1
markdown-it-py v3.0.0
└── mdurl v0.1.2
pygments v2.19.1
typing-extensions v4.12.2
Enter fullscreen mode Exit fullscreen mode

就会看到丰富套件的相依套件都还在,并不会因为没有其他套件需要用到而一并被删除。

要特别说明的是,uv pip指令的速度比pip要快,即使是这一点,也要使用魔鬼uv pip女郎pip

使用 uv 管理 Python 专案

前面的使用很方便,不过有两个主要的问题:

  1. 没有记录以及快速重复 Python 执行环境的方法,如果需要在另一个环境执行同样的 Python 程序,就必须自己手动建立 Python 执行环境。
  2. 继承不再需要的增补套件,就像刚才看到的那样,在删除套件的过程中,即使某些套件不再需要其他套件,也不会被删除。

要解决上述问题,就必须改用专案的形式来管理。

只管理单一码档的专案

说到专案,好像很复杂,不过uv提供了一种最简单的专案形式,只不过是单个程序码档的专案,uv把专案相关资料写入Python程序原始码中,特别适用于设计一些小工具。

比如说,有一个程序需要使用 Python 3.13 以上的版本执行,就可以利用uv init创建这个程序档:

# uv init --script cow3.py --python 3.13
Initialized script at `cow3.py`
Enter fullscreen mode Exit fullscreen mode

如果观察该文件的内容:

# cat cow3.py
# /// script
# requires-python = ">=3.13"
# dependencies = []
# ///


def main() -> None:
    print("Hello from cow3.py!")


if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

就会看到程序码开头有一段特殊格式的注释解,这是给uv看的锐数据(元数据),标明了所需要的Python环境。

为专案加入套件

我们可以进一步使用uv add指定所需的套件:

# uv add --script cow3.py cowsay rich
Updated `cow3.py`
Enter fullscreen mode Exit fullscreen mode

uv同样会修改原始码:

# cat cow3.py
# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "cowsay",
#     "rich",
# ]
# ///


def main() -> None:
    print("Hello from cow3.py!")


if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

您可以在注解中的dependencies表格中看到刚刚指定的套件。接着我们修改程序码,以便确认可以使用指定的套件:

# cat cow3.py
# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "cowsay",
#     "rich",
# ]
# ///

from cowsay import cow
from rich import print


def main() -> None:
    cow('hello, uv')
    print('hello, rich')

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

执行看看:

# uv run cow3.py
Reading inline script metadata from `cow3.py`
Installed 5 packages in 106ms
  _________
| hello, uv |
  =========
         \
          \
            ^__^
            (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
hello, rich
Enter fullscreen mode Exit fullscreen mode

你可以看到 uv 会先读取记录在程序原始码内注解的精确数据,为该程序建立一个临时的虚拟环境,然后根据需求安装所需的套件,最后正确执行。如果指定的 Python 版本尚未安装,uv 也会自动下载安装一致的版本。

利用这样的方式,只要将该文件复制到其他安装有 uv 的地方,就可以自动创建相关的Python环境执行了。

删除套件

如果要删除套件,只需使用uv remove指令即可,例如:

# uv remove --script cow3.py rich
Updated `cow3.py`
Enter fullscreen mode Exit fullscreen mode

就可以看到原始码中的注解也修改了:

# cat cow3.py
# /// script
# requires-python = ">=3.13"
# dependencies = [
#     "cowsay",
# ]
# ///

from cowsay import cow
from rich import print


def main() -> None:
    cow('hello, uv')
    print('hello, rich')

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

重新执行就会出错,因为码中会用到的丰富的程序套件已经被我们删除了:

# uv run .\cow3.py
Reading inline script metadata from `cow3.py`
Traceback (most recent call last):
  File "C:\Users\meebo\code\python\test\cow3.py", line 9, in <module>
    from rich import print
ModuleNotFoundError: No module named 'rich'
Enter fullscreen mode Exit fullscreen mode

管理以资料夹为基础的专案

使用文件作为专案虽然很方便,不过大多数情况下专案都没有这么简单,因此 uv 提供另一种以数据夹为基础的专案形式,同样是在使用过的uv init指令建立之前使用,例如:

# uv init test_uv
Initialized project `test-uv` at `C:\Users\meebo\code\python\test\test_uv`
Enter fullscreen mode Exit fullscreen mode

它会查找您提供的专案名称,帮助建立数据夹:

# cd test_uv
# ls

    Directory: C:\Users\meebo\code\python\test\test_uv

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2025/1/7 下午 05:21            109 .gitignore
-a---          2025/1/7 下午 05:21              5 .python-version
-a---          2025/1/7 下午 05:21             85 hello.py
-a---          2025/1/7 下午 05:21            153 pyproject.toml
-a---          2025/1/7 下午 05:21              0 README.md
Enter fullscreen mode Exit fullscreen mode

进入资料夹你会发现,uv还帮你建立了许多档案:

  • .gitignore:uv会帮你把专案建立成git存储库,并且帮你写好.gitignore文件,避免Python执行过程产生的临时文档等也提交到存储库内:

    # cat .\.gitignore
    # Python-generated files
    __pycache__/
    *.py[oc]
    build/
    dist/
    wheels/
    *.egg-info
    
    # Virtual environments
    .venv
    
  • .python-version:记录这个专案使用的Python版本:

    # cat .\.python-version
    3.13
    
  • hello.py:计划档:默认会帮助建立一个主计划档,内容如下:

    # cat .\hello.py
    def main():
        print("Hello from test-uv!")
    
    if __name__ == "__main__":
        main()    
    
  • pyproject.toml:这个专案的锐度数据,其实就是前面单一程序档形式的专案在原始码注解的内容:

    # cat .\pyproject.toml
    [project]
    name = "test-uv"
    version = "0.1.0"
    description = "Add your description here"
    readme = "README.md"
    requires-python = ">=3.13"
    dependencies = []
    

    之后增减所需套件时,可以把相关资讯记录在此档案中。

  • README.ME:空的markdown档,前期让你撰写专案说明用。

如果需要,在创建专案时也可以使用--python指定想要使用的 Python 版本。

执行专案内的计划

要执行专案内的程序代码,同样是使用uv run

# uv run hello.py
Using CPython 3.13.1
Creating virtual environment at: .venv
Hello from test-uv!
Enter fullscreen mode Exit fullscreen mode

第一次执行时,uv会引用专案内的设置,建立虚拟环境,放在.venv数据夹内,之后所有的操作都是利用这个虚拟环境:

# ls

    Directory: C:\Users\meebo\code\python\test\test_uv

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2025/1/7 下午 05:37                .venv
-a---          2025/1/7 下午 05:21            109 .gitignore
-a---          2025/1/7 下午 05:21              5 .python-version
-a---          2025/1/7 下午 05:21             85 hello.py
-a---          2025/1/7 下午 05:21            153 pyproject.toml
-a---          2025/1/7 下午 05:21              0 README.md
-a---          2025/1/7 下午 05:37            114 uv.lock
Enter fullscreen mode Exit fullscreen mode

另外,还要增加uv.lock档:

# cat .\uv.lock
version = 1
requires-python = ">=3.13"

[[package]]
name = "test-uv"
version = "0.1.0"
source = { virtual = "." }
Enter fullscreen mode Exit fullscreen mode

该文件会由 uv 管理,引用 pyproject.toml 内部记录的套件推导出所有相依套件的版本与关系。

安装套件

要在专案内安装与删除套件,都和前面单一程序码档的操作一样,只是记录数据的位置修改成独立的文件,而不是在原始码内的注解,例如:

# uv add cowsay rich
Resolved 6 packages in 380ms
Prepared 5 packages in 598ms
Installed 5 packages in 101ms
 + cowsay==6.1
 + markdown-it-py==3.0.0
 + mdurl==0.1.2
 + pygments==2.19.1
 + rich==13.9.4
Enter fullscreen mode Exit fullscreen mode

此时 pyproject.toml 档内就会记录刚刚加入的套件以及对应的版本:

# cat .\pyproject.toml
[project]
name = "test-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "cowsay>=6.1",
    "rich>=13.9.4",
]
Enter fullscreen mode Exit fullscreen mode

但如果查看 uv.lock 档,就会看到所有安装的相依套件信息:

# cat .\uv.lock
version = 1
requires-python = ">=3.13"

[[package]]
name = "cowsay"
version = "6.1"
source = { registry = "https://pypi.org/simple" }
wheels = [
    { url = "https://files.pythonhosted.org/packages/f1/13/63c0a02c44024ee16f664e0b36eefeb22d54e93531630bd99e237986f534/cowsay-6.1-py3-none-any.whl", hash = "sha256:274b1e6fc1b966d53976333eb90ac94cb07a450a700b455af9fbdf882244b30a", size = 25560 },
]

[[package]]
name = "markdown-it-py"
version = "3.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
    { name = "mdurl" },
]
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
]

[[package]]
name = "mdurl"
version = "0.1.2"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
]

[[package]]
name = "pygments"
version = "2.19.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
]

[[package]]
name = "rich"
version = "13.9.4"
source = { registry = "https://pypi.org/simple" }
dependencies = [
    { name = "markdown-it-py" },
    { name = "pygments" },
]
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
wheels = [
    { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
]

[[package]]
name = "test-uv"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
    { name = "cowsay" },
    { name = "rich" },
]

[package.metadata]
requires-dist = [
    { name = "cowsay", specifier = ">=6.1" },
    { name = "rich", specifier = ">=13.9.4" },
]
Enter fullscreen mode Exit fullscreen mode

在修改文件最下方可以看到此专案依赖cowsay 与 rich 两个套件,而 rich 又依赖 markdown-it-py 以及 pygments 两个套件。如果往上找,就会看到 markdwon-it-py 又依赖 mdurl 套件,所以刚刚执行程序的时候就会看到一共安装了 5 个套件。uv.lock 是依赖 pyproject.toml 自动产生的内容,我们不应该是它的内容。

如果你想了解专案中套件的关系,也可以使用uv tree指令:

# uv tree
Resolved 6 packages in 2ms
test-uv v0.1.0
├── cowsay v6.1
└── rich v13.9.4
    ├── markdown-it-py v3.0.0
    │   └── mdurl v0.1.2
    └── pygments v2.19.1
Enter fullscreen mode Exit fullscreen mode

就可以树状结构图刚才看到从uv.lock档中解析出来的关系。

更新套件

如果要更新特定套件,可以使用uv lock --upgrade-package指令:

# uv lock --upgrade-package cowsay
Resolved 6 packages in 385ms
Enter fullscreen mode Exit fullscreen mode

如果要更新所有套件,则可以uv lock --upgrade

# uv lock --upgrade
Resolved 18 packages in 304ms
Enter fullscreen mode Exit fullscreen mode

更新套件都会遵循 pyproject.toml 档内的限制,安装符合条件的版本。

执行套件提供的指令

在专案中,uv run除了可以执行程序码档之外,也可以执行套件所提供的指令,例如以下先安装httpie套件:

# uv add httpie
Resolved 19 packages in 3.65s
Prepared 13 packages in 13.89s
Installed 13 packages in 224ms
 + certifi==2024.12.14
 + charset-normalizer==3.4.1
 + colorama==0.4.6
 + defusedxml==0.7.1
 + httpie==3.2.4
 + idna==3.10
 + multidict==6.1.0
 + pip==24.3.1
 + pysocks==1.7.1
 + requests==2.32.3
 + requests-toolbelt==1.0.0
 + setuptools==75.7.0
 + urllib3==2.3.0
Enter fullscreen mode Exit fullscreen mode

然后,就可以执行该套件提供的http指令了:

# uv run http -p=b GET https://flagtech.github.io/flag.txt
FLAG
  ______ _               _____
 |  ____| |        /\   / ____|
 | |__  | |       /  \ | |  __
 |  __| | |      / /\ \| | |_ |
 | |    | |____ / ____ \ |__| |
 |_|    |______/_/    \_\_____|
Enter fullscreen mode Exit fullscreen mode

删除套件

如果要删除套件,同样是用uv remove指令,例如:

# uv remove cowsay
Resolved 18 packages in 20ms
Uninstalled 1 package in 4ms
 - cowsay==6.1
Enter fullscreen mode Exit fullscreen mode

手动修改 pyproject.toml 文件

你也可以自己手动修改 pyproject.toml 文件,例如现在的 pyproject.toml 文件内容如下:

# cat .\pyproject.toml
[project]
name = "test-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "httpie>=3.2.4",
    "rich>=13.9.4",
]
Enter fullscreen mode Exit fullscreen mode

如果把其中有依赖关系的表格中的httpie那一行删除:

# cat .\pyproject.toml
[project]
name = "test-uv"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "rich>=13.9.4",
]
Enter fullscreen mode Exit fullscreen mode

这个时候必须执行uv lock指令,让 uv.lock 文件的内容与 pyproject.toml 文件一致:

# uv lock
Resolved 5 packages in 12ms
Removed certifi v2024.12.14
Removed charset-normalizer v3.4.1
Removed colorama v0.4.6
Removed defusedxml v0.7.1
Removed httpie v3.2.4
Removed idna v3.10
Removed multidict v6.1.0
Removed pip v24.3.1
Removed pysocks v1.7.1
Removed requests v2.32.3
Removed requests-toolbelt v1.0.0
Removed setuptools v75.7.0
Removed urllib3 v2.3.0
Enter fullscreen mode Exit fullscreen mode

这里会看到 uv.lock 档的更新情况,你可以看到它移除了 httpie 及其依赖的套件,不过要注意的是,这只是纸上作业,了 uv.lock 档的内容而已,实际上这些套件都没有移除,你可以透过uv pip list来查看目前安装的套件:

# uv pip list
Package            Version
------------------ ----------
certifi            2024.12.14
charset-normalizer 3.4.1
colorama           0.4.6
defusedxml         0.7.1
httpie             3.2.4
idna               3.10
markdown-it-py     3.0.0
mdurl              0.1.2
multidict          6.1.0
pip                24.3.1
pygments           2.19.1
pysocks            1.7.1
requests           2.32.3
requests-toolbelt  1.0.0
rich               13.9.4
setuptools         75.7.0
urllib3            2.3.0
Enter fullscreen mode Exit fullscreen mode

要按照 uv.lock 内容增删套件,就必须再执行uv sync让实际的 Python 环境与 uv.lock 档的内容一致:

# uv sync
Resolved 5 packages in 1ms
Uninstalled 13 packages in 395ms
 - certifi==2024.12.14
 - charset-normalizer==3.4.1
 - colorama==0.4.6
 - defusedxml==0.7.1
 - httpie==3.2.4
 - idna==3.10
 - multidict==6.1.0
 - pip==24.3.1
 - pysocks==1.7.1
 - requests==2.32.3
 - requests-toolbelt==1.0.0
 - setuptools==75.7.0
 - urllib3==2.3.0
Enter fullscreen mode Exit fullscreen mode

到这里,才真正删除了 httpie 及其依赖的套件,如果再次使用uv pip list检测视:

# uv pip list
Package        Version
-------------- -------
markdown-it-py 3.0.0
mdurl          0.1.2
pygments       2.19.1
rich           13.9.4
Enter fullscreen mode Exit fullscreen mode

可以看httpie相关的套件真的都不见了。这也和严重使用uv pippip管理套件不一样的地方,以专案形式管理时,删除套件时会循uv.lock档中推导出的依赖关系,把已经没有套件依赖的套件一并移除,只留下需要的套件。

复制专案

利用这样的方式,只需将专案资料夹复制到其他安装有ux的地方,重新执行专案就会自动建置Python环境安装套件,不需要手动辛苦建立了。

使用套件提供的工具指令

有些套件提供了可以直接执行的指令,例如刚才的cowsay套件就提供了cowsay可以在终端机执行的指令,如果只是想使用这些指令,uv提供的有uvx指令可以不用先建立专案或者Python执行环境,就直接执行这些指令,例如可以:

# uvx cowsay -t 'hello, uv'
Installed 1 package in 16ms
  _________
| hello, uv |
  =========
         \
          \
            ^__^
            (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Enter fullscreen mode Exit fullscreen mode

uvx同样会根据套件建立临时的虚拟环境,并安装必要的套件。实际上uvx指令是uv tool run的快捷指令,你也可以这样执行:

# uv tool run cowsay -t 'hello, uv'
  _________
| hello, uv |
  =========
         \
          \
            ^__^
            (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Enter fullscreen mode Exit fullscreen mode

如果要执行的指令与套件不同名称,就必须--from指定套件名称。举例来说,如果想要使用前面看过的 httpie 套件提供的http指令获取特定网址的内容,就可以这样下指令:

# uvx --from httpie http -p=b GET https://flagtech.github.io/flag.txt
Installed 17 packages in 291ms
FLAG
  ______ _               _____
 |  ____| |        /\   / ____|
 | |__  | |       /  \ | |  __
 |  __| | |      / /\ \| | |_ |
 | |    | |____ / ____ \ |__| |
 |_|    |______/_/    \_\_____|
Enter fullscreen mode Exit fullscreen mode

你可以看到它会先安装--from选项指定的套件,然后再执行指令。

将套件提供的指令安装到系统上

如果某个套件中的指令很好用,你也可以uv tool install把它安装到系统上,例如刚才 httpie 套件中的http指令,就很适合安装起来替代curl使用:

# uv tool install httpie
Resolved 17 packages in 560ms
Installed 17 packages in 224ms
 + certifi==2024.12.14
 + charset-normalizer==3.4.1
 + colorama==0.4.6
 + defusedxml==0.7.1
 + httpie==3.2.4
 + idna==3.10
 + markdown-it-py==3.0.0
 + mdurl==0.1.2
 + multidict==6.1.0
 + pip==24.3.1
 + pygments==2.19.1
 + pysocks==1.7.1
 + requests==2.32.3
 + requests-toolbelt==1.0.0
 + rich==13.9.4
 + setuptools==75.7.0
 + urllib3==2.3.0
Installed 3 executables: http.exe, httpie.exe, https.exe
Enter fullscreen mode Exit fullscreen mode

uv 会建立一个独立的虚拟环境来安装套件,接着就可以直接执行套件中的指令:

# http -p=b GET https://flagtech.github.io/flag.txt
FLAG
  ______ _               _____
 |  ____| |        /\   / ____|
 | |__  | |       /  \ | |  __
 |  __| | |      / /\ \| | |_ |
 | |    | |____ / ____ \ |__| |
 |_|    |______/_/    \_\_____|
Enter fullscreen mode Exit fullscreen mode

如果想知道实际安装的路径,可以通过uv tool dir指令:

# uv tool dir
C:\Users\meebo\AppData\Roaming\uv\tools
Enter fullscreen mode Exit fullscreen mode

若有需要,也可以通过以下uv tool upgrade更新这些指令的版本:

# uv tool upgrade httpie
Nothing to upgrade
Enter fullscreen mode Exit fullscreen mode

往后如果不再需要这个套件的指令,也可以删除删除uv tool uninstall

# uv tool uninstall httpie
Uninstalled 3 executables: http.exe, httpie.exe, https.exe
Enter fullscreen mode Exit fullscreen mode

本文介绍了 uv 的几种使用方式,应该可以让大家了解使用 uv 来管理 Python 环境的好处,不但执行速度快,也可以在太古中使用不同多种工具的麻烦。

文章来源:https://dev.to/codemee/shi-yong-uv-guan-li-python-huan-jing-53hg
PREV
如何成为一名开发人员 - 第 4 部分:推荐阅读编程文化常识 Python C++ 和 C Linux
NEXT
使用 Javascript 和 CSS 进行简单的电子邮件验证