运行脚本
Python 脚本是一个旨在独立执行的文件,例如,使用 python <script>.py
。 使用 uv 执行脚本可确保脚本依赖得到管理,而无需手动管理环境。
注意
如果您不熟悉 Python 环境:每个 Python 安装都有一个可以安装软件包的环境。 通常,建议创建虚拟环境以隔离每个脚本所需的软件包。 uv 会自动为您管理虚拟环境,并且倾向于使用声明式方法来处理依赖。
运行没有依赖的脚本
如果您的脚本没有依赖,您可以使用 uv run
执行它
同样,如果您的脚本依赖于标准库中的模块,则无需执行任何其他操作
可以向脚本提供参数
此外,可以直接从 stdin 读取脚本
或者,如果您的 shell 支持here-documents
请注意,如果在项目中使用 uv run
,即带有 pyproject.toml
的目录,它将在运行脚本之前安装当前项目。 如果您的脚本不依赖于该项目,请使用 --no-project
标志跳过此步骤
$ # Note: the `--no-project` flag must be provided _before_ the script name.
$ uv run --no-project example.py
有关在项目中工作的更多详细信息,请参见项目指南。
运行有依赖的脚本
当您的脚本需要其他包时,必须将它们安装到脚本运行的环境中。 uv 倾向于按需创建这些环境,而不是使用具有手动管理依赖的长期存在的虚拟环境。 这需要显式声明脚本所需的依赖。 通常,建议使用项目或内联元数据来声明依赖,但 uv 也支持按调用请求依赖。
例如,以下脚本需要 rich
。
import time
from rich.progress import track
for i in track(range(20), description="For example:"):
time.sleep(0.05)
如果执行时未指定依赖,则此脚本将失败
$ uv run --no-project example.py
Traceback (most recent call last):
File "/Users/astral/example.py", line 2, in <module>
from rich.progress import track
ModuleNotFoundError: No module named 'rich'
使用 --with
选项请求依赖
如果需要特定版本,可以将约束添加到请求的依赖
可以通过重复 --with
选项来请求多个依赖。
请注意,如果在项目中使用 uv run
,这些依赖将除了项目的依赖之外包含在内。 要选择退出此行为,请使用 --no-project
标志。
创建 Python 脚本
Python 最近添加了一种用于内联脚本元数据的标准格式。 它允许选择 Python 版本和定义依赖。 使用 uv init --script
初始化具有内联元数据的脚本
声明脚本依赖
内联元数据格式允许在脚本本身中声明脚本的依赖。
uv 支持为您添加和更新内联脚本元数据。 使用 uv add --script
声明脚本的依赖
这将在脚本顶部添加一个 script
部分,使用 TOML 声明依赖
# /// script
# dependencies = [
# "requests<3",
# "rich",
# ]
# ///
import requests
from rich.pretty import pprint
resp = requests.get("https://peps.pythonlang.cn/api/peps.json")
data = resp.json()
pprint([(k, v["title"]) for k, v in data.items()][:10])
uv 将自动创建一个具有运行脚本所需依赖的环境,例如
$ uv run example.py
[
│ ('1', 'PEP Purpose and Guidelines'),
│ ('2', 'Procedure for Adding New Modules'),
│ ('3', 'Guidelines for Handling Bug Reports'),
│ ('4', 'Deprecation of Standard Modules'),
│ ('5', 'Guidelines for Language Evolution'),
│ ('6', 'Bug Fix Releases'),
│ ('7', 'Style Guide for C Code'),
│ ('8', 'Style Guide for Python Code'),
│ ('9', 'Sample Plaintext PEP Template'),
│ ('10', 'Voting Guidelines')
]
重要
当使用内联脚本元数据时,即使 uv run
是 在项目中使用的,也将忽略项目的依赖。 不需要 --no-project
标志。
uv 还遵循 Python 版本要求
# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///
# Use some syntax added in Python 3.12
type Point = tuple[float, float]
print(Point)
注意
即使为空,也必须提供 dependencies
字段。
uv run
将搜索并使用所需的 Python 版本。 如果未安装 Python 版本,则将下载该版本 — 有关更多详细信息,请参见有关Python 版本的文档。
使用 Shebang 创建可执行文件
可以添加 Shebang 以使脚本无需使用 uv run
即可执行 — 这使得运行位于您的 PATH
或当前文件夹中的脚本变得容易。
例如,创建一个名为 greet
的文件,其中包含以下内容
确保您的脚本是可执行的,例如,使用 chmod +x greet
,然后运行脚本
在此上下文中也支持声明依赖,例如
#!/usr/bin/env -S uv run --script
#
# /// script
# requires-python = ">=3.12"
# dependencies = ["httpx"]
# ///
import httpx
print(httpx.get("https://example.com"))
使用替代的包索引
如果您希望使用替代的包索引来解析依赖,则可以使用 --index
选项提供索引
这会将包数据包含在内联元数据中
如果您需要身份验证才能访问包索引,请参阅包索引文档。
锁定依赖
uv 支持使用 uv.lock
文件格式锁定 PEP 723 脚本的依赖。 与项目不同,必须使用 uv lock
显式锁定脚本
运行 uv lock --script
将在脚本旁边创建一个 .lock
文件(例如,example.py.lock
)。
锁定后,后续操作(如 uv run --script
、uv add --script
、uv export --script
和 uv tree --script
)将重用锁定的依赖,并在必要时更新锁定文件。
如果不存在此类锁定文件,则像 uv export --script
这样的命令仍将按预期运行,但不会创建锁定文件。
提高可重现性
除了锁定依赖之外,uv 还支持内联脚本元数据的 tool.uv
部分中的 exclude-newer
字段,以限制 uv 仅考虑在特定日期之前发布的发行版。 这对于提高脚本在稍后时间运行时重现性非常有用。
日期必须指定为 RFC 3339 时间戳(例如,2006-12-02T02:07:43Z
)。
# /// script
# dependencies = [
# "requests",
# ]
# [tool.uv]
# exclude-newer = "2023-10-16T00:00:00Z"
# ///
import requests
print(requests.__version__)
使用不同的 Python 版本
uv 允许在每个脚本调用中请求任意 Python 版本,例如
有关请求 Python 版本的更多详细信息,请参见Python 版本请求文档。
使用 GUI 脚本
在 Windows 上,uv
将使用 pythonw
运行以 .pyw
扩展名结尾的脚本
from tkinter import Tk, ttk
root = Tk()
root.title("uv")
frm = ttk.Frame(root, padding=10)
frm.grid()
ttk.Label(frm, text="Hello World").grid(column=0, row=0)
root.mainloop()
同样,它也适用于依赖
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QGridLayout
app = QApplication(sys.argv)
widget = QWidget()
grid = QGridLayout()
text_label = QLabel()
text_label.setText("Hello World!")
grid.addWidget(text_label)
widget.setLayout(grid)
widget.setGeometry(100, 100, 200, 50)
widget.setWindowTitle("uv")
widget.show()
sys.exit(app.exec_())
下一步
要了解有关 uv run
的更多信息,请参见命令参考。
或者,继续阅读以了解如何使用 uv 运行和安装工具。