【发布时间】:2023-09-06 19:29:01
【问题描述】:
我正在为一个项目开发一个命令行工具集。最终的工具应该支持很多子命令,像这样
foo command1 [--option1 [value]?]*
所以可以有类似的子命令
foo create --option1 value --
foo make file1 --option2 --option3
该工具使用 argparse 库来处理命令行参数和帮助功能等。
一些额外的要求和限制:
-
所有子命令的某些选项和功能都是相同的(例如解析 YAML 配置文件等)
-
一些子命令的编码既快速又简单,因为它们例如只需调用外部 bash 脚本即可。
-
一些子命令会很复杂,因此代码很长。
-
应该提供基本工具的帮助以及单个子命令的帮助:
帮助 可用的命令有:make、create、add、xyz
foo 帮助制作 make 子命令的详细信息
-
子命令的错误代码应该是统一的(就像“找不到文件”的错误代码一样)
出于调试目的和在最小可行版本的自包含功能方面取得进展,我想开发一些子命令作为自包含脚本和模块,例如
make.py
可以导入到主 foo.py 脚本中,然后作为两者调用
make.py --option1 value etc.
和
foo.py make --option1 value
现在,我的问题是:用最少的冗余来模块化这样一个复杂的 CLI 工具的最佳方法是什么(例如,参数定义和解析应该只编码在一个组件中)?
选项 1:将所有内容放在一个大脚本中,但这将变得难以管理。
选项 2: 在单个模块/文件中开发子命令的功能(如 make.py、add.py);但必须保持可调用(通过if __name__ == '__main__' ...)。
然后可以将子命令模块中的函数导入到主脚本中,并将子命令中的解析器和参数添加为子解析器。
选项3:主脚本可以简单地重新格式化对子进程的子命令的调用,就像这样
subprocess.run('./make.py {arguments}', shell=True, check=True, text=True)
【问题讨论】:
-
python 库 'click' 提供了这个功能
-
Typer 也是如此,如果你习惯了 FastAPI
-
我认为您的问题比重复链接要大得多。
parents是一种懒人在多个子解析器中定义相同参数的方式。但懒惰的程序员也知道他们可以编写辅助函数来执行重复性任务。但我认为 SO 不是解决程序结构问题的好论坛。范围太大,太受制于意见。一旦您编写了基本的子解析器代码,您就已经用尽了argparse提供的工具。在模块中运行子命令和分区不是argparse问题。 -
没错。最佳实践问题,如果它们是关于 Stack Exchange 的主题,属于 Software Engineering,而不是这里。 Stack Overflow 仅适用于有关在编程实践中遇到的狭窄、具体问题的问题,这些问题可以得到规范的答案。
-
Typer(以及,为了 API 目的,FastAPI)看起来很有前途!谢谢!
标签: python command-line-interface command-line-arguments argparse