The Hitchhiker‘s Guide to Python 命令行应用实战:从 argparse 到 Click、docopt、Plac 与框架选型 The Hitchhikers Guide to Python 命令行应用实战从 argparse 到 Click、docopt、Plac 与框架选型【免费下载链接】python-guidePython best practices guidebook, written for humans.项目地址: https://gitcode.com/gh_mirrors/py/python-guide本文依据仓库文档 docs/scenarios/cli.rst 编写。该文档是《Python 开发者指南》The Hitchhikers Guide to Python项目 python-guide场景指南Scenario Guide for Python Applications一章的组成部分面向命令行应用Command-line Applications这一具体开发场景梳理了 Python 生态中从轻量解析到完整框架的 CLI 构建工具链。读完本文你将理解命令行应用的参数模型参数/选项/子命令掌握 Click、docopt、Plac、Cliff、Cement、Python Fire 六类工具的定位与核心用法并能根据项目规模做出合理的选型决策。什么是命令行应用命令行应用Command-line Applications也常被称为控制台应用 Console Applications是设计用来从文本界面例如 shell使用的计算机程序。与图形界面程序不同命令行应用与用户的交互完全通过文本完成用户启动程序时通常需要向其传入各种输入。命令行应用的输入通常分为两类参数arguments / parameters有时也称作参数或子命令sub-commands用于指定程序要操作的对象或要执行的子功能选项options / flags / switches用于开关或调整程序的行为细节。Python 社区中有大量广为人知、形态各异的命令行应用它们是理解 CLI 设计的绝佳参照物其中包括应用定位grep纯文本数据检索工具通过正则与选项组合完成行级过滤curl基于 URL 语法进行数据传输的工具httpie命令行 HTTP 客户端被定位为更友好的 cURL 替代品git分布式版本控制系统是多级子命令型 CLI 的典型代表mercurial分布式版本控制系统主要用 Python 编写是用 Python 写出大型 CLI的活样本尤其值得注意git与mercurial它们都是主程序 子命令架构主程序只做少量基础参数解析然后把控制权交给具体的子命令git checkout、hg log……。这种架构模式直接催生了后文将介绍的 Cliff 等框架的设计思想。在 Python 标准库层面argparse 是官方提供的参数解析模块也是许多第三方库如 Plac的底层基础。本文接下来按照由轻到重的顺序逐一介绍指南推荐/提及的工具。Click可组合的命令行接口创建套件clickCommand-Line Interface Creation Kit是 Python 生态中最流行的 CLI 库之一目标是用尽可能少的代码、以可组合的方式创建命令行接口。它高度可配置同时又开箱即用地提供了良好的默认行为。Click 的核心设计是装饰器驱动用click.command()把普通函数变成命令用click.option()声明选项、click.argument()声明位置参数选项解析结果会作为关键字参数注入函数import click click.command() click.option(--count, default1, helpNumber of greetings.) click.option(--name, promptYour name, helpThe person to greet.) def hello(count, name): Simple program that greets NAME for a total of COUNT times. for _ in range(count): click.echo(fHello, {name}!) if __name__ __main__: hello()这段代码已经自动获得了--help帮助信息、--count的默认值与类型校验、--name未提供时的交互式 promptpromptYour name。click.echo()负责跨平台的文本输出自动处理 Unicode 编码问题。Click 的其他常用特性包括选项类型与取值校验typeint、typeclick.Choice([easy, hard])、typeclick.Path(existsTrue)等标志开关click.option(--verbose, is_flagTrue)子命令组合Groupclick.group()可以把多个命令聚合为git式的多级命令确认与隐藏输入prompt配合hide_inputTrue、confirmation_promptTrue可实现密码式输入上下文对象click.pass_context允许在父子命令之间传递共享状态。由于高度可配置但默认值友好Click 被大量知名项目采用适合从几行的脚本级 CLI 到几十个命令的大型工具链。docopt用 POSIX 风格用法说明直接生成解析器docopt的思路与 Click 完全不同它不写解析代码而是让你直接以 POSIX 风格的用法说明usage instruction字符串描述接口docopt 解析这段文档本身返回一个字典形式的解析结果。Naval Fate. Usage: naval_fate.py ship new name... naval_fate.py ship name move x y [--speedkn] naval_fate.py ship shoot x y naval_fate.py mine (set|remove) x y [--moored | --drifting] naval_fate.py (-h | --help) naval_fate.py --version Options: -h --help Show this screen. --version Show version. --speedkn Speed in knots [default: 10]. --moored Moored (anchored) mine. --drifting Drifting mine. from docopt import docopt if __name__ __main__: arguments docopt(__doc__, versionNaval Fate 2.0) print(arguments)运行后arguments是一个普通字典键为各选项/参数名如arguments[--speed]、arguments[name]布尔标志为True/False可选值为给定字符串或None。docopt 的价值在于声明式与文档即接口Usage:块同时充当帮助文本和解析规范几乎没有学习成本特别适合对易读、直观有强烈诉求的开发者。需要注意的是docopt 解析得到的只是字典其余逻辑子命令分发、类型转换等需要你自行编写。Placargparse 的声明式封装Plac是对 Python 标准库argparse的一个简单封装其核心理念是参数解析器是被推断出来的而不是被命令式地写出来的。它通过一个声明式接口把 argparse 的绝大部分复杂度隐藏起来。最简单的用法是直接把函数签名当作接口——Plac 从函数的位置参数、关键字参数及其默认值、类型注解推断出 CLI 接口import plac def main(x, y, verboseFalse): A minimal example: x and y are positional, verbose is a flag. if verbose: print(f{x} {y}) print(x y) if __name__ __main__: plac.call(main)对于需要更精确控制如类型、帮助文本的场景可以使用plac.annotationsimport plac plac.annotations( numplac.Annotation(a number to double, typefloat), timesplac.Annotation(how many times, typeint, kindoption), ) def main(num, times1): Double a number repeatedly. for _ in range(times): num * 2 print(num) if __name__ __main__: plac.call(main)Plac 的设计目标人群非常明确非资深用户、程序员、系统管理员、科研人员以及一般意义上给自己写一次性脚本的人——他们选择写 CLI 仅仅因为这样快捷简单。如果你的诉求是用最少仪式感把脚本变成可执行命令Plac 是极轻量的选择。Cliff面向多级子命令的框架CliffCommand Line Interface Framework是一个用于构建命令行程序的框架其最大特点是基于 setuptools 的 entry points 提供子命令、输出格式化器和其他扩展机制。框架的定位是创建svn、git这类多级命令主程序只负责少量基础参数解析然后调用具体的子命令完成工作。Cliff 的典型应用结构是定义App子类并指定一个CommandManager由后者通过 entry points 自动发现所有注册的子命令import sys from cliff.app import App from cliff.commandmanager import CommandManager class DemoApp(App): def __init__(self): super().__init__( descriptionA demo cliff application, version0.1.0, command_managerCommandManager(demo.cli), ) def main(argvsys.argv[1:]): app DemoApp() return app.run(argv) if __name__ __main__: sys.exit(main())子命令通过实现cliff.command.Command或cliff.lister.Lister、cliff.show.ShowOne等数据输出类来编写并在项目的setup.py/pyproject.toml中注册 entry point如demo.cli demo.commands。Cliff 还内置了漂亮的表格化输出Lister与字段化输出ShowOne适合 OpenStack 这类拥有成百上千个命令、需要插件化扩展的大型项目。Cement从微框架到巨型框架的 CLI 应用平台Cement是一个进阶的 CLI 应用程序框架目标是为简单和复杂的命令行应用引入一个标准化、功能齐全的平台在不牺牲质量的前提下支持快速开发。Cement 非常灵活其适用范围横跨微框架micro-framework的简洁到巨型框架mega-framework的复杂度。Cement 以控制器Controller 应用App为核心模型from cement import App, Controller, ex class BaseController(Controller): class Meta: label base ex(helpsay hello to the world) def hello(self): self.app.render(Hello World!) class MyApp(App): class Meta: label myapp controllers [BaseController] with MyApp() as app: app.run()Cement 内置了大量开箱即用的功能配置config后端支持文件配置、日志log后端、模板渲染output/self.app.render、插件系统、扩展系统、钩子hooks等并通过handler抽象允许替换每一层的实现。如果你的 CLI 需要配置文件、日志、插件化等应用级能力而不是单纯解析参数Cement 提供了完整的骨架。Python Fire从任意 Python 对象自动生成 CLIPython Fire是 Google 开源的库其口号是从任何 Python 对象自动生成命令行接口。它彻底颠覆了手写解析器的思路你把一个函数、类、模块甚至字典交给fire.Fire()它就自动暴露为可调用的命令行界面。import fire def hello(nameWorld): Greet someone. return fHello {name}! if __name__ __main__: fire.Fire(hello)运行python hello.py --namePython即可得到Hello Python!。把fire.Fire()指向一个类时类的方法会自动成为子命令指向模块时模块内的函数和类都会暴露出来。官方列出的典型使用场景包括更方便地在命令行调试 Python 代码为既有代码快速创建 CLI 接口无需改动被包装的对象在 REPL 中交互式地探索代码简化 Python 与 Bash或其他 shell之间的切换。Python Fire 几乎零样板代价是你对接口形态的控制力较弱——它适合内部工具、原型验证与调试而非对外发布的、需要精心设计帮助文本的产品级 CLI。选型参考不同规模下如何选择综合上述工具可以按项目形态给出如下选型思路这也对应了 cli.rst 文档的推荐结构场景推荐理由一次性脚本顺手加个参数Plac/Fire声明式或零代码最快上手常规工具需要好用的帮助与类型校验Click装饰器模型可组合默认行为友好文档即接口追求直观docopt解析器由 Usage 文档直接生成git式多级子命令、插件化大型工具Cliffsetuptools entry points 驱动子命令与扩展需要配置、日志、插件等应用级能力Cement提供标准化、功能齐全的应用平台调试/原型/交互式探索Fire从任意对象自动生成 CLI对于规模介于两者之间的项目Click 往往是平衡点而如果项目已经依赖标准库、不希望引入第三方依赖argparse 依然是官方可靠的底线方案Plac 正是站在它肩膀上做减法。延伸阅读本文内容在仓库中的原始出处为 docs/scenarios/cli.rst它是项目文档 contents.rst.inc 中Scenario Guide for Python Applications场景指南一节的组成部分该节与 docs/scenarios/web.rst、docs/scenarios/scrape.rst、docs/scenarios/db.rst、docs/scenarios/serialization.rst 等并列共同构成按应用场景选型工具的实践地图。仓库的文档构建配置见 docs/conf.pySphinx 工程source_suffix .rstmaster_doc index构建依赖见 requirements.txt。如果希望进一步深入 CLI 之外的 Python 实践可继续阅读仓库中的 docs/writing/structure.rst项目结构、docs/writing/style.rst代码风格与 docs/writing/tests.rst测试它们是编写任何规模 Python 命令行应用的通用底座。【免费下载链接】python-guidePython best practices guidebook, written for humans.项目地址: https://gitcode.com/gh_mirrors/py/python-guide创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考