创建 Typer CLI 应用程序
创建 Typer CLI 应用程序
在本节中,您将创建与支持最小打字员CLI应用程序--help
,-v
和--version
选项。为此,您将使用显式 Typer 应用程序。这种类型的应用程序适用于包含带有多个选项和参数的多个命令的大型项目。
继续并rptodo/cli.py
在文本编辑器中打开并输入以下代码:
"""This module provides the RP To-Do CLI."""
# rptodo/cli.py
from typing import Optional
import typer
from rptodo import __app_name__, __version__
app = typer.Typer()
def _version_callback(value: bool) -> None:
if value:
typer.echo(f"{__app_name__} v{__version__}")
raise typer.Exit()
@app.callback()
def main(
version: Optional[bool] = typer.Option(
None,
"--version",
"-v",
help="Show the application's version and exit.",
callback=_version_callback,
is_eager=True,
)
) -> None:
return
Typer 广泛使用 Python 类型提示,因此在本教程中,您也将使用它们。这就是为什么您从导入Optional
from开始typing
。接下来,您导入typer
. 最后,您从您的包中导入__app_name__
和。__version__
rptodo
以下是其余代码的工作原理:
-
第 10 行创建了一个显式的 Typer 应用程序
app
. -
第 12 到 15 行定义了
_version_callback()
. 此函数采用名为的布尔参数value
。如果value
是True
,则该函数使用 打印应用程序的名称和版本echo()
。之后,它会引发typer.Exit
异常以干净地退出应用程序。 -
第 19 行定义了
version
,它的类型是Optional[bool]
。这意味着它可以是 ofbool
或None
type。该version
参数默认为一个typer.Option
对象,它允许您创建打字员的命令行选项。 -
第 20 行
None
作为第一个参数传递给 的初始值设定项Option
。此参数是必需的,并提供选项的默认值。 -
第 21 和 22 行设置
version
选项的命令行名称:-v
和--version
。 -
第 23 行提供了
help
该version
选项的消息。 -
第 24行将回调函数 , 附加
_version_callback()
到version
选项,这意味着运行该选项会自动调用该函数。 -
第 25行将
is_eager
参数设置为True
。此参数告诉 Typerversion
命令行选项优先于当前应用程序中的其他命令。
有了这些代码,您就可以创建应用程序的入口点脚本了。这就是您将在下一节中执行的操作。
创建入口点脚本
您几乎已准备好第一次运行您的待办事项应用程序。在此之前,您应该为应用程序创建一个入口点脚本。您可以通过几种不同的方式创建此脚本。在本教程中,您将使用包__main__.py
内的模块来完成rptodo
。__main__.py
在 Python 包中包含模块使您能够使用命令将包作为可执行程序运行python -m rptodo
。
返回到您的代码编辑器并__main__.py
从rptodo/
目录中打开。然后添加以下代码:
"""RP To-Do entry point script."""
# rptodo/__main__.py
from rptodo import cli, __app_name__
def main():
cli.app(prog_name=__app_name__)
if __name__ == "__main__":
main()
在 中__main__.py
,您首先导入cli
并__app_name__
从rptodo
. 然后你定义main()
. 在此函数中,您使用 调用 Typer 应用程序cli.app()
,将应用程序的名称传递给prog_name
参数。提供一个值以prog_name
确保您的用户--help
在其命令行上运行该选项时获得正确的应用程序名称。
通过这最后的添加,您就可以第一次运行您的待办事项应用程序了。移动到终端窗口并执行以下命令:
(venv) $ python -m rptodo -v
rptodo v0.1.0
(venv) $ python -m rptodo --help
Usage: rptodo [OPTIONS] COMMAND [ARGS]...
Options:
-v, --version Show the application's version and exit.
--install-completion Install completion for the current shell.
--show-completion Show completion for the current shell, to copy it
or customize the installation.
--help Show this message and exit.
第一个命令运行-v
选项,显示应用程序的版本。第二个命令运行--help
选项以显示整个应用程序的用户友好帮助消息。Typer 会自动为您生成并显示此帮助消息。
使用 pytest 设置初始 CLI 测试
您将在本节中运行的最后一个操作是为您的待办事项应用程序设置初始测试套件。为此,您tests
使用名为test_rptodo.py
. 如前所述,您将使用 pytest 编写和运行单元测试。
测试Typer 应用程序很简单,因为该库与 pytest 集成得很好。您可以使用调用的 Typer 类CliRunner
来测试应用程序的 CLI。CliRunner
允许您创建一个运行程序,您可以使用它来测试应用程序的 CLI 如何响应现实世界的命令。
返回到您的代码编辑器并test_rptodo.py
从tests/
目录中打开。输入以下代码:
# tests/test_rptodo.py
from typer.testing import CliRunner
from rptodo import __app_name__, __version__, cli
runner = CliRunner()
def test_version():
result = runner.invoke(cli.app, ["--version"])
assert result.exit_code == 0
assert f"{__app_name__} v{__version__}\n" in result.stdout
下面是这段代码的作用:
- 3个线进口
CliRunner
从typer.testing
。 - 第 5 行从您的
rptodo
包中导入一些必需的对象。 - 第 7 行通过实例化
CliRunner
. - 第 9 行定义了用于测试应用程序版本的第一个单元测试。
- 第10点的调用
.invoke()
上runner
运行与应用程序--version
选项。您将此调用的结果存储在result
. - 第 11 行断言应用程序的退出代码(
result.exit_code
) 等于0
检查应用程序是否成功运行。 - 第 12 行断言应用程序的版本存在于标准输出中,可通过
result.stdout
.
Typer'sCliRunner
是Click'sCliRunner
的子类。因此,它的.invoke()
方法返回一个Result
对象,该对象保存使用目标参数和选项运行 CLI 应用程序的结果。Result
对象提供了几个有用的属性和特性,包括应用程序的退出代码和标准输出。有关更多详细信息,请查看类文档。
现在您已经为 Typer CLI 应用程序设置了第一个单元测试,您可以使用 pytest 运行测试。返回命令行并python -m pytest tests/
从项目的根目录执行:
========================= test session starts =========================
platform linux -- Python 3.9.5, pytest-6.2.4, py-1.10.0, pluggy-0.13.1
rootdir: .../rptodo
plugins: Faker-8.1.1, cov-2.12.0, celery-4.4.7
collected 1 item
tests/test_rptodo.py . [100%]
========================== 1 passed in 0.07s ==========================
就是这样!您第一次成功运行了测试套件!是的,到目前为止您只有一项测试。但是,您将在接下来的部分中添加更多内容。如果您想挑战自己的测试技能,也可以添加自己的测试。
随着待办事项应用程序的骨架就位,现在您可以考虑设置待办事项数据库以使其准备好使用。这就是您将在下一节中执行的操作。
步骤 3:准备待办事项数据库以供使用
到目前为止,您已经为待办事项应用程序组合了一个 CLI,创建了一个入口点脚本,并首次运行了该应用程序。您还为应用程序设置并运行了一个最小的测试套件。下一步是定义您的应用程序将如何初始化并连接到待办事项数据库。
您将使用JSON文件来存储有关待办事项的数据。JSON 是一种轻量级的数据交换格式,人类可读可写。Python 的标准库包括json
,这是一个提供开箱即用的 JSON 文件格式支持的模块。这就是您将用来管理待办事项数据库的内容。
您可以通过单击下面的链接并转到source_code_step_3/
目录来下载本节的完整代码:
在本节结束时,您将编写用于创建、连接和初始化待办事项数据库的代码,以便可以使用。然而,第一步是定义您的应用程序将如何在您的文件系统中找到待办事项数据库。
设置应用程序的配置
您可以使用不同的技术来定义应用程序如何连接和打开文件系统上的文件。您可以动态提供文件路径,创建一个环境变量来保存文件路径,创建一个用于存储文件路径的配置文件,等等。
注意:配置文件,也称为配置文件,是程序员用来为给定程序或应用程序提供初始参数和设置的一种文件。
在本教程中,您将为您的待办事项应用程序提供主目录中的配置文件,以存储数据库的路径。为此,您将使用pathlib
文件系统路径和configparser
处理配置文件。这两个包都可以在 Python 标准库中使用。
现在返回到您的代码编辑器并config.py
从rptodo/
. 输入以下代码:
"""This module provides the RP To-Do config functionality."""
# rptodo/config.py
import configparser
from pathlib import Path
import typer
from rptodo import (
DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name_
)
CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__))
CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini"
def init_app(db_path: str) -> int:
"""Initialize the application."""
config_code = _init_config_file()
if config_code != SUCCESS:
return config_code
database_code = _create_database(db_path)
if database_code != SUCCESS:
return database_code
return SUCCESS
def _init_config_file() -> int:
try:
CONFIG_DIR_PATH.mkdir(exist_ok=True)
except OSError:
return DIR_ERROR
try:
CONFIG_FILE_PATH.touch(exist_ok=True)
except OSError:
return FILE_ERROR
return SUCCESS
def _create_database(db_path: str) -> int:
config_parser = configparser.ConfigParser()
config_parser["General"] = {"database": db_path}
try:
with CONFIG_FILE_PATH.open("w") as file:
config_parser.write(file)
except OSError:
return DB_WRITE_ERROR
return SUCCESS
以下是这段代码的作用的细分:
-
4号线进口
configparser
。该模块提供了ConfigParser
类,它允许您处理具有类似于INI 文件结构的配置文件。 -
地铁5吨线的进口
Path
从pathlib
。此类提供了一种跨平台的方式来处理系统路径。 -
7号线进口
typer
。 -
第 9 到 11 行从
rptodo
. -
第 13 行创建
CONFIG_DIR_PATH
保存应用程序目录的路径。要获取此路径,请get_app_dir()
使用应用程序的名称作为参数进行调用。此函数返回一个字符串,表示您可以在其中存储配置的目录的路径。 -
第 14 行定义
CONFIG_FILE_PATH
保存配置文件本身的路径。 -
第 16 行定义了
init_app()
. 该函数初始化应用程序的配置文件和数据库。 -
第 18 行调用
_init_config_file()
helper 函数,您在第 26 到 35 行中定义了该函数。调用此函数会使用Path.mkdir()
. 它还使用Path.touch()
. 最后,_init_config_file()
如果在创建目录和文件期间发生错误,则返回正确的错误代码。SUCCESS
如果一切顺利,它就会返回。 -
第 19 行检查在创建目录和配置文件的过程中是否发生错误,第 20 行相应地返回错误代码。
-
第 21 行调用
_create_database()
helper 函数,该函数创建待办事项数据库。如果在创建数据库时发生某些事情,此函数将返回适当的错误代码。SUCCESS
如果进程成功则返回。 -
第 22 行检查在创建数据库期间是否发生错误。如果是,则第 23 行返回相应的错误代码。
-
SUCCESS
如果一切正常,第 24 行返回。
使用此代码,您已完成设置应用程序的配置文件以存储待办事项数据库的路径。您还添加了代码以将待办事项数据库创建为 JSON 文件。现在您可以编写代码来初始化数据库并准备好使用它。这就是您将在下一节中执行的操作。
准备好待办事项数据库以供使用
- 点赞
- 收藏
- 关注作者
评论(0)