创建和打包命令行工具¶
本指南将引导您创建和打包一个独立的命令行应用程序,该应用程序可以使用 pipx 进行安装。pipx 是一个用于创建和管理 Python 虚拟环境 并将包的可执行脚本(以及可用的手册页)暴露给命令行使用的工具。
创建包¶
首先,为 项目 创建一个源目录。为了举例,我们将构建一个简单的工具,根据命令行参数为一个人输出问候语(一个字符串)。
待办事项
在另一篇指南或讨论中提供关于 Python 包最佳结构的建议,并在此处链接。
此项目将遵循 src-layout,最终像这样的文件树,顶层文件夹和包名是 greetings
.
├── pyproject.toml
└── src
└── greetings
├── cli.py
├── greet.py
├── __init__.py
└── __main__.py
负责工具功能的实际代码将存储在 greet.py
文件中,以主模块命名。
import typer
from typing_extensions import Annotated
def greet(
name: Annotated[str, typer.Argument(help="The (last, if --title is given) name of the person to greet")] = "",
title: Annotated[str, typer.Option(help="The preferred title of the person to greet")] = "",
doctor: Annotated[bool, typer.Option(help="Whether the person is a doctor (MD or PhD)")] = False,
count: Annotated[int, typer.Option(help="Number of times to greet the person")] = 1
):
greeting = "Greetings, "
if doctor and not title:
title = "Dr."
if not name:
if title:
name = title.lower().rstrip(".")
else:
name = "friend"
if title:
greeting += f"{title} "
greeting += f"{name}!"
for i in range(0, count):
print(greeting)
上述函数接收几个关键字参数,这些参数决定了要输出的问候语如何构造。现在,构造命令行界面以提供相同的参数,这在 cli.py
中完成。
import typer
from .greet import greet
app = typer.Typer()
app.command()(greet)
if __name__ == "__main__":
app()
命令行界面使用 typer 构建,这是一个基于 Python 类型提示的易于使用的 CLI 解析器。它开箱即用地提供了自动补全和样式美观的命令行帮助。另一个选择是 argparse
,一个包含在 Python 标准库中的命令行解析器。它足以满足大多数需求,但需要大量的代码(通常在 cli.py
中)才能正常运行。另外,docopt 可以仅基于 docstring 创建 CLI 接口;鼓励高级用户使用 click(typer
即基于此)。
现在,添加一个空的 __init__.py
文件,将项目定义为一个常规的 导入包。
__main__.py
文件标志着应用程序通过 runpy
运行时(即 python -m greetings
,这对于扁平布局可以直接工作,但对于 src 布局需要安装包)的主要入口点,因此在此处初始化命令行界面。
if __name__ == "__main__":
from greetings.cli import app
app()
注意
为了能够直接从 项目源目录 调用命令行接口,即作为 python src/greetings
,可以在此文件中放置一个特定的“技巧”;请参阅 从带有 src-layout 的源运行命令行接口 以了解更多信息。
pyproject.toml
¶
项目的 元数据 放置在 pyproject.toml 中。pyproject 元数据键 和 [build-system]
表格可以按照 编写你的 pyproject.toml 中描述的方式填写,添加对 typer
的依赖(本教程使用版本 0.12.3)。
为了让项目被识别为命令行工具,还需要添加一个 console_scripts
入口点(参见 创建可执行脚本)作为 子键。
[project.scripts]
greet = "greetings.cli:app"
现在,项目的源目录已准备好转换为 分发包,使其可安装。
使用 pipx
安装包¶
按照 安装独立命令行工具 中描述的步骤安装 pipx
后,安装你的项目。
$ cd path/to/greetings/
$ pipx install .
这将暴露我们定义为入口点的可执行脚本,并使 greet
命令可用。让我们测试一下。
$ greet
Greetings, friend!
$ greet --doctor Brennan
Greetings, Dr. Brennan!
$ greet --title Ms. Parks
Greetings, Ms. Parks!
$ greet --title Mr.
Greetings, Mr. mr!
由于此示例使用 typer
,您现在也可以通过使用 --help
选项调用程序来获取程序使用概述,或者通过 --install-completion
选项配置自动补全。
如果只是运行程序而不永久安装它,可以使用 pipx run
,它将为其创建一个临时(但已缓存)的虚拟环境。
$ pipx run --spec . greet --doctor
然而,这种语法有点不切实际;由于我们上面定义的入口点名称与包名不匹配,我们需要明确说明要运行哪个可执行脚本(即使只存在一个)。
然而,针对此问题有一个更实际的解决方案,即 pipx run
特有的入口点。可以在 pyproject.toml
中定义如下:
[project.entry-points."pipx.run"]
greetings = "greetings.cli:app"
多亏了这个入口点(它 必须 与包名匹配),pipx
会将该可执行脚本选作默认脚本并运行它,从而使此命令成为可能:
$ pipx run . --doctor
结论¶
你现在知道如何打包用 Python 编写的命令行应用程序了。下一步可以是分发你的包,这意味着将其上传到 包索引,最常见的是 PyPI。要做到这一点,请遵循 打包你的项目 中的说明。完成之后,别忘了 研究一下 你的包是如何被接收的!