依赖脚本运行
当脚本需要其他包时,这些包必须安装到脚本运行的环境中。uv偏好按需创建环境,而不是使用手动管理依赖的长期虚拟环境。
例如,以下脚本需要rich
包:
import timefrom rich.progress import track
for i in track(range(20), description="For example:"): time.sleep(0.05)
不指定依赖直接执行会失败:
$ uv run --no-project example.pyTraceback (most recent call last): File "/Users/astral/example.py", line 2, in <module> from rich.progress import trackModuleNotFoundError: No module named 'rich'
使用--with
选项请求依赖:
uv run --with rich example.py
如需特定版本,可以添加约束:
uv run --with "rich>=10.0" example.py
多个依赖可以重复使用--with
选项。
创建Python脚本
Python最近添加了内联脚本元数据(inline script metadata)的标准格式,允许选择Python版本和定义依赖。使用uv init --script
初始化带内联元数据的脚本:
uv init --script hello.py
声明脚本依赖
内联元数据格式允许在脚本本身中声明依赖。uv支持为你添加和更新内联脚本元数据。使用uv add --script
声明脚本依赖:
uv add --script example.py requests rich
这会在脚本顶部添加使用TOML格式的script
部分:
# /// script# dependencies = [# "requests<3",# "rich",# ]# ///
import requestsfrom rich.pretty import pprint
resp = requests.get("https://peps.python.org/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'),│ ...]
重要:使用内联脚本元数据时,即使在项目中使用uv run
,项目的依赖也会被忽略,无需--no-project
标志。
uv也尊重Python版本要求:
# /// script# requires-python = ">=3.12"# dependencies = []# ///
# 使用Python 3.12新增的语法type Point = tuple[float, float]print(Point)
注意:即使为空,也必须提供dependencies
字段。
uv run
会搜索并使用所需的Python版本。如果未安装,Python版本会自动下载。
使用shebang创建可执行文件
可以添加shebang使脚本无需使用uv run
即可执行——这样便于运行PATH中或当前文件夹的脚本。
例如,创建名为greet
的文件:
#!/usr/bin/env uv runprint("Hello world")
确保脚本可执行(如chmod +x greet
),然后运行:
./greet
这种情况下也支持依赖声明:
#!/usr/bin/env -S uv run --script# /// script# requires-python = ">=3.12"# dependencies = ["httpx"]# ///
import httpxprint(httpx.get("https://example.com"))
使用替代包索引
如果要使用替代包索引(package index)解析依赖,可以使用--index
选项:
uv run --with httpx --index https://pypi.example.com/simple/ script.py
如果需要认证访问包索引,请参考包索引文档。
锁定依赖
uv支持使用uv.lock
文件格式为PEP 723脚本锁定依赖。与项目不同,脚本必须使用uv lock
显式锁定:
uv lock --script example.py
运行uv lock --script
会在脚本旁边创建.lock
文件(如example.py.lock
)。
锁定后,后续的uv run --script
、uv add --script
、uv export --script
和uv tree --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 requestsprint(requests.__version__)
使用不同Python版本
uv允许在每次脚本调用时请求任意Python版本:
uv run --python 3.11 script.pyuv run --python python3.12 script.py
使用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()
带依赖的GUI脚本同样可以工作:
import sysfrom 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_())