用 Python 解析命令行参数( 二 )

就个人而言 , 我希望 Python 有开关 , 但这 永远 、永远不会 发生。
GNU 时代
GNU 项目出现了 , 并为他们实现的传统 Unix 命令行工具引入了更长的格式参数 , 比如--file-format foo 。当然 , 我们这些 Unix 程序员很讨厌这样 , 因为打字太麻烦了 , 但是就像我们这些旧时代的恐龙一样 , 我们输了 , 因为用户喜欢更长的选项 。我从来没有写过任何使用 GNU 风格选项解析的代码 , 所以这里没有代码示例 。
GNU 风格的参数也接受像 -f foo 这样的短名 , 也必须支持 。所有这些选择都给程序员带来了更多的工作量 , 因为他们只想知道用户要求的是什么 , 然后继续进行下去 。但用户得到了更一致的用户体验:长格式选项、短格式选项和自动生成的帮助 , 使用户不必再试图阅读臭名昭著的难以解析的 手册 页面(参见 ps 这个特别糟糕的例子) 。
但我们正在讨论 Python?你现在已经接触了足够多(太多?)的命令行的历史 , 对如何用我们最喜欢的语言来编写 CLI 有了一些背景知识 。Python 在命令行解析方面给出了类似的几个选择:自己解析 ,  自给自足(batteries-included)的方式 , 以及大量的第三方方式 。你选择哪一种取决于你的特定情况和需求 。
首先 , 自己解析
你可以从 sys 模块中获取程序的参数 。
import sysif __name__ == '__main__':   for value in sys.argv:       print(value)自给自足
在 Python 标准库中已经有几个参数解析模块的实现: getopt 、 optparse  , 以及最近的 argparse。argparse 允许程序员为用户提供一致的、有帮助的用户体验 , 但就像它的 GNU 前辈一样 , 它需要程序员做大量的工作和“ 模板代码 ”才能使它“奏效” 。
from argparse import ArgumentParserif __name__ == "__main__":   argparser = ArgumentParser(description='My Cool Program')   argparser.add_argument("--foo", "-f", help="A user supplied foo")   argparser.add_argument("--bar", "-b", help="A user supplied bar")      results = argparser.parse_args()   print(results.foo, results.bar)好处是当用户调用 --help 时 , 有自动生成的帮助 。但是 自给自足 (batteries included)的优势呢?有时 , 你的项目情况决定了你对第三方库的访问是有限的 , 或者说是没有 , 你不得不用 Python 标准库来“凑合” 。
CLI 的现代方法
然后是 Click。Click 框架使用 装饰器 的方式来构建命令行解析 。突然间 , 写一个丰富的命令行界面变得有趣而简单 。在装饰器的酷炫和未来感的使用下 , 很多复杂的东西都消失了 , 用户惊叹于自动支持关键字补完以及上下文帮助 。所有这些都比以前的解决方案写的代码更少 。任何时候 , 只要你能写更少的代码 , 还能把事情做好 , 就是一种胜利 。而我们都想要胜利 。
import click@click.command()@click.option("-f", "--foo", default="foo", help="User supplied foo.")@click.option("-b", "--bar", default="bar", help="User supplied bar.")def echo(foo, bar):    """My Cool Program       It does stuff. Here is the documentation for it.    """    print(foo, bar)   if __name__ == "__main__":    echo()你可以在 @click.option 装饰器中看到一些与 argparse 相同的模板代码 。但是创建和管理参数分析器的“工作”已经被抽象化了 。现在 , 命令行参数被解析 , 而值被赋给函数参数 , 从而函数 echo 被魔法般地调用 。
在 Click 接口中添加参数就像在堆栈中添加另一个装饰符并将新的参数添加到函数定义中一样简单 。
但是 , 等等 , 还有更多!Typer 建立在 Click 之上 , 是一个更新的 CLI 框架 , 它结合了 Click 的功能和现代 Python 类型提示。使用 Click 的缺点之一是必须在函数中添加一堆装饰符 。CLI 参数必须在两个地方指定:装饰符和函数参数列表 。Typer 免去你造轮子 去写 CLI 规范 , 让代码更容易阅读和维护 。
import typercli = typer.Typer()@cli.command()def echo(foo: str = "foo", bar: str = "bar"):    """My Cool Program       It does stuff. Here is the documentation for it.    """    print(foo, bar)   if __name__ == "__main__":    cli()


推荐阅读