使用uv构建Python命令行工具:从代码到全局命令
在 Python 开发中,我们经常需要创建一些命令行工具来提高工作效率。本文将手把手教你如何使用现代 Python 打包工具 uv,将一个简单的 Python 模块构建成可以通过 nzs-tool myhello Alice 这种形式调用的全局命令行工具。
❓ 为什么选择 uv?
uv 是 Astral 团队(ruff 的开发者)推出的新一代 Python 包管理工具,它比传统的 pip 快 10-100 倍,并且原生支持 pyproject.toml 标准。使用 uv 管理 Python 项目,不仅能获得极快的安装速度,还能享受更现代化的开发体验。
白话理解:uv 是用 Rust 写的超快 Python 包管理器,可以理解为 pip 的”涡轮增压版”——做的事情和 pip 一样,但速度快了几十倍,还自带项目管理功能。
👀 最终效果预览
完成本教程后,你将能够:
- 编写 Python 命令行工具代码
- 通过 uv 安装到本地环境
- 在终端直接运行
nzs-tool myhello Alice这样的命令
1 | $ nzs-tool myhello Alice |
📁 第一步:项目初始化
首先,创建项目目录并初始化 uv 项目。
1 | # 创建项目目录 |
执行 uv init 后,uv 会自动创建一个 pyproject.toml 文件,包含基本的项目配置。
🏗️ 第二步:规划项目结构
采用 src 布局是 Python 社区的推荐实践,可以避免导入时的一些常见问题。
1 | nzs-tool/ |
创建这些目录和文件:
1 | mkdir -p src/nzs_tool |
💻 第三步:编写命令行工具代码
我们将使用 Click 库来构建命令行接口。Click 是一个优雅的 Python CLI 库,通过装饰器就能轻松创建复杂的命令行工具。
首先,添加 Click 依赖:
1 | uv add click |
然后在 src/nzs_tool/cli.py 中编写代码:
1 | import click |
代码解析:
@click.group()创建一个命令组,支持子命令@cli.command()注册子命令,name参数指定命令名称@click.argument()定义位置参数(如myhello后面的名字)click.echo()是跨平台的打印函数,比print更强大
📄 第四步:配置 pyproject.toml
这是最关键的一步。我们需要在 pyproject.toml 中配置两件事:
- 项目的元数据(名称、版本、依赖等)
- 命令行入口点(告诉 Python 如何调用我们的命令)
编辑 pyproject.toml 文件:
1 | [project] |
关键点解析:
[project.scripts]是配置命令行入口的地方(也叫entry_points/console_scripts)nzs-tool = "nzs_tool.cli:cli"表示:- 创建名为
nzs-tool的命令 - 调用
nzs_tool.cli模块中的cli函数
- 创建名为
cli函数就是我们之前在cli.py中用@click.group()装饰的函数
白话理解:
[project.scripts](即 entry_points / console_scripts)的作用是告诉 Python”安装完之后,在终端输入这个命令就能启动这个程序”——就像给程序创建了一个桌面快捷方式,双击(输入命令)就能运行。
⚙️ 第五步:安装工具
现在,我们可以将工具安装到本地环境中。uv 提供了两种安装方式:
方式一:可编辑安装(推荐开发阶段)
1 | uv pip install -e . |
-e 参数表示可编辑安装,对源代码的修改会立即生效,无需重新安装,非常适合开发调试。
方式二:直接安装
1 | uv pip install . |
这种方式会将当前代码打包并安装,后续修改需要重新安装才能生效。
安装完成后,可以验证是否安装成功:
1 | uv pip list | grep nzs-tool |
⌨️ 第六步:运行命令
安装成功后,你就可以在终端直接运行命令了!
1 | # 运行子命令 |
如果你使用的是虚拟环境但没有激活,可以使用 uv run 来执行:
白话理解:虚拟环境就是给每个项目一个独立的”沙盒”,装的包互不影响——就像每个项目有自己的工具箱,不会和别的项目的工具混在一起。没有激活虚拟环境时,
uv run能帮你自动找到正确的工具箱来运行命令。
1 | uv run nzs-tool myhello Alice |
uv run 会自动识别当前项目环境,非常方便。
✨ 进阶:添加更多功能
1. 添加选项参数
Click 支持各种参数类型,包括选项(option):
1 |
|
使用方式:
1 | nzs-tool repeat Alice --count 3 |
2. 添加配置文件支持
你可以让工具读取配置文件,实现更灵活的功能:
1 | import json |
3. 添加颜色输出
Click 内置了颜色支持:
1 |
|
🔍 调试技巧
直接运行 Python 文件
在开发过程中,可以直接运行 Python 文件来调试:
1 | python src/nzs_tool/cli.py myhello Alice |
这需要你在 cli.py 文件末尾添加 if __name__ == "__main__": cli() 代码(我们已经在代码中添加了)。
使用 uv run 运行未安装的命令
即使没有安装,也可以使用 uv run 直接运行:
1 | uv run python src/nzs_tool/cli.py myhello Alice |
查看入口点脚本位置
安装后,可以查看生成的入口点脚本:
1 | # 查看脚本位置 |
📦 发布到 PyPI(可选)
如果你想和全世界分享你的工具,可以发布到 PyPI:
1. 构建分发包
1 | uv build |
这会在 dist/ 目录下生成 .tar.gz 源码包和 .whl 二进制包。
2. 发布
1 | # 首次发布需要配置 PyPI token |
发布后,任何人都可以通过以下命令安装:
1 | uv pip install nzs-tool |
✅ 常见问题
Q1: 命令找不到怎么办?
检查虚拟环境是否激活,或者使用 uv run nzs-tool。
Q2: 修改代码后命令没有变化?
如果使用可编辑安装(-e),修改应该立即生效。如果使用普通安装,需要执行 uv pip install .。
Q3: Windows 上运行报错?
Click 和 uv 都完美支持 Windows。如果遇到路径问题,确保在命令提示符或 PowerShell 中运行,而不是在 WSL 中。
Q4: 如何添加依赖?
使用 uv add package-name 添加依赖,会自动更新 pyproject.toml 和 uv.lock。
📝 总结
通过本教程,我们完成了一个完整的 Python 命令行工具开发流程:
- 使用 uv 初始化项目
- 编写 Click 命令行代码
- 配置 pyproject.toml 的入口点
- 通过 uv 安装到本地
- 在终端直接调用命令
这种开发模式的优势:
- 开发效率高:uv 的极速安装和可编辑模式
- 用户体验好:用户只需一个命令就能安装和运行
- 标准化:完全遵循 Python 打包规范(PEP 621)
- 易扩展:可以轻松添加更多子命令和功能
现在,你已经掌握了使用 uv 构建 Python 命令行工具的全部技巧。快去创建属于你自己的命令行工具吧!
🎯 自我检验清单
完成本教程后,用以下清单检验自己的掌握程度:
- 能使用
uv init初始化一个新的 Python 项目,并理解生成的pyproject.toml各字段含义 - 能使用
src布局组织项目代码,并解释为什么包名要用下划线而命令名用短横线 - 能使用 Click 的
@click.group()、@click.command()、@click.argument()、@click.option()创建带子命令的 CLI 工具 - 能正确配置
[project.scripts]入口点,将 Python 函数映射为终端命令 - 能区分可编辑安装(
-e)和普通安装的区别,并根据场景选择合适的方式 - 能使用
uv run在未激活虚拟环境的情况下运行项目命令 - 能使用
uv build构建分发包,并理解.tar.gz和.whl的区别 - 能独立排查”命令找不到”等常见问题,知道从虚拟环境、入口点配置等方面定位原因