第二十六章 命令行解析器(标准库)

argparse 模块是标准库中最大的模块之一,拥有大量的配置选项。 本章只是演示了其中最基础的一些特性,帮助你入门。同时我也不建议使用它来在大量的生产环境上使用,因为我们有更好的选择, 一个第三模块 Plumbum。我会在后面的章节介绍它。

一、基本步骤

为了解析命令行选项
你首先要创建一个 ArgumentParser 实例, 并使用 add_argument()方法声明你想要支持的选项。

无意义的示例

必须一个py 文件 prog.py , 并写入如下内容

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

试着在命令行里执行如下代码

$ python3 prog.py --help
usage: prog.py [-h]

optional arguments:
  -h, --help  show this help message and exit


可以看到,即使没有做太多设置,这个脚本已经实现了命令行工具了,并且默认就会有 --help 参数。
--help 也可以简写为 -h

二、添加必须的位置参数

位置参数就是,必须为程序提供的,并且不需要使用 ---

继续编辑我们的 prog.py 文件。
这次我们可以使用实例的 add_argument() 函数来添加一个位置参数。
这个位置参数是必须的,不给其传参,将会抛出一个错误提示。

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("show")
args = parser.parse_args()
print(args.show)

上面的代码中, 字符串的 'show' 被传给 add_argument() 方法。
最后他会变成实例的一个属性,用来接收在命令行里传入的实际的值。
最后一行我们打印了这个属性,也就可以实现打印出命令行里传入的实际的值了。

我们来执行一下

$ python3 prog.py hello
hello

这个时候使用 --help,你会发现帮助信息并没有表明目前的这个位置参数是用来做什么的。

$ python3 prog.py --help
usage: prog.py [-h] show

positional arguments:
  show

optional arguments:
  -h, --help  show this help message and exit

所以,接下来我们就来添加位置参数的帮助信息

三、 使用 help 添加帮助信息

$ cat prog.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("show", help="打印出你输入的字符串")
args = parser.parse_args()
print(args.show)

再次执行,会看到我们添加的帮助信息

$ python3 prog.py -h
usage: prog.py [-h] show

positional arguments:
  show        打印出你输入的字符串

optional arguments:
  -h, --help  show this help message and exit

四、添加更多的逻辑

我们可以在执行了 parser.parse_args() 之后,添加更多的逻辑,用于实现更多的功能。
比如,下面的示例计算 2 的任意次方。

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("square",
                    type=int,
                    help="打印出 2 的幂值, 要求传入一个整数")
args = parser.parse_args()
print(2 ** args.square)

这里因为是算术运算,所以需要用 type=int 把传入的参数声明为整型。

执行结果如下:

$ python3 power.py 4
16

五、制作一个 copy 命令行工具

为了展示位置参数(Positional arguments),下面写一个cp.py,实现简单的文件复制功能。

import argparse
import shutil


def _parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "source",
        help="指定要复制的文件,支持相对路径和绝对路径",
    )
    parser.add_argument(
        "target",
        help="指定要复制的路径,包括拷贝后的文件名",
    )
    return parser.parse_args()


if __name__ == '__main__':
    args = _parse_args()
    shutil.copy(src=args.source, dst=args.target)

cp.py命令后,第一个参数被识别为source,第二个参数被识别为target,然后执行复制。在parse_args()之后,sys.argv的参数列表,变成了结构化的args

args的类型,是一个<class 'argparse.Namespace'>)。

如果执行python cp.py cp.py cp2.py,那么不会有任何显示信息,成功执行复制操作。

如果多一个或者少一个参数呢?

$ python3 cp.py one.py
usage: cp.py [-h] source target
cp.py: error: the following arguments are required: target

$ python3 cp.py one.py two.py three.py
usage: cp.py [-h] source target
cp.py: error: unrecognized arguments: three.py

这就比直接使用sys.argv的可靠性要高多了。

注意这里并没有对源文件是否存在进行检测。

六、可选参数

可选参数就是可有可无的参数,一般用 - 或者 --表示。

可选参数就是需要使用 - 或者 -- 后面紧跟的是一个关键字。比如 -h也称为短参数 ,--help也称为长参数。

这个两种可以同时存在于程序中,也可以只出现一种。

让我们继续改写 cp.py 程序,让其具有查看版本的参数 -v--version

import argparse
import shutil


def _parse_args():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "source",
        help="指定要复制的文件,支持相对路径和绝对路径",
    )
    
    parser.add_argument(
        "target",
        help="指定要复制的路径,包括拷贝后的文件名",
    )
    
    parser.add_argument(
        '-v',
        '--version',
        action='version',  # 遇到参数时的动作,默认值 store
        version='%(prog)s 1.1',  ## 实际打印出来的内容
        help='查看程序版本',

    )
    return parser.parse_args()


if __name__ == '__main__':
    args = _parse_args()
    shutil.copy(src=args.source, dst=args.target)
$ python3 cp.py  -v
cp.py 1.1 1.1

针对上面的示例说一下

action 用于当使用某一个参数时,将会触发的动作,这些动作是内置好的
       这里的 version 就是其中一个动作
vervion 其对应的值就是,使用 -v 参数后要显示的内容,其中 `prog` 是内置的一个变量,其值是脚本文件名。

action='version' 和 version 通常一起配套使用

关于 action 可选的内置好的值

  • store 保存参数值,可能会先将参数值转换成另一个数据类型。若没有显式指定动作,则默认为该动作,会把参数的值保存在一个变量上。
  • store_const 保存一个被定义为参数规格一部分的值,而不是一个来自参数解析而来的值。这通常用于实现非布尔值的命令行标记。
  • store_ture/store_false 保存相应的布尔值。这两个动作被用于实现布尔开关, 比如linux系统中好多命令经常会 -R 参数,表示是否递归,使用这个参数表示为 True , 不使用为 False
  • append 将值保存到一个列表中。若参数重复出现,则保存多个值。
  • append_const 将一个定义在参数规格中的值保存到一个列表中。
  • version 打印关于程序的版本信息,然后退出

在每个 add_argument() 调用中,dest 参数指定解析命令行传入的参数的变量名字。 help 参数被用来生成自定义的帮助信息。action 参数指定跟属性对应的处理逻辑, 通常的值为 store ,被用来存储某个值或将多个参数值收集到一个列表中。 下面的参数收集所有剩余的命令行参数到一个列表中。在本例中它被用来构造一个文件名列表:

parser.add_argument(dest='filenames',metavar='filename', nargs='*')

下面的参数根据参数是否存在来设置一个 Boolean 标志:

parser.add_argument('-v', dest='verbose', action='store_true',
                    help='verbose mode')

下面的参数接受一个单独值并将其存储为一个字符串:

parser.add_argument('-o', dest='outfile', action='store',
                    help='output file')

下面的参数说明允许某个参数重复出现多次,并将它们追加到一个列表中去。 required 标志表示该参数至少要有一个。-p--pat 表示两个参数名形式都可使用。

parser.add_argument('-p', '--pat',metavar='pattern', required=True,
                    dest='patterns', action='append',
                    help='text pattern to search for')

最后,下面的参数说明接受一个值,但是会将其和可能的选择值做比较,以检测其合法性:

parser.add_argument('--speed', dest='speed', action='store',
                    choices={'slow','fast'}, default='slow',
                    help='search speed')

一旦参数选项被指定,你就可以执行 parser.parse() 方法了。 它会处理 sys.argv 的值并返回一个结果实例。 每个参数值会被设置成该实例中 add_argument() 方法的 dest 参数指定的属性值。

还很多种其他方法解析命令行选项。 例如,你可能会手动的处理 sys.argv 或者使用 getopt模块。 但是,如果你采用本节的方式,将会减少很多冗余代码,底层细节 argparse 模块已经帮你处理了。 你可能还会碰到使用 optparse 库解析选项的代码。 尽管 optparseargparse 很像,但是后者更先进,因此在新的程序中你应该使用它。

  • action - 在命令行遇到此参数时要采取的基本操作类型。
  • nargs - 应该使用的命令行参数的数量。
  • const - 某些操作和nargs选择所需的常量值。
  • default - 如果命令行中不存在参数,则生成的值。
  • type - 应转换命令行参数的类型。
  • choices - 参数允许值的容器。
  • required - 是否可以省略命令行选项(仅限选项)。
  • help - 对参数的作用的简要描述。
  • metavar - 用法消息中参数的名称。
  • dest - 要添加到返回的对象的属性的名称 parse_args()。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容