Python 做为一个脚本语言, 可以很方便地写各种工具. 当你在服务端要运行一个工具或服务时, 输入参数似乎是一种硬需 (当然你也可以通过配置文件来实现).
如果要以命令行执行, 那你需要解析一个命令行参数解析的模块来帮你做这个苦力活.
Python 本身就提供了三个命令行参数解析模块, 我这里罗列一下它们的大致情况供你了解.
getopt, 只能简单的处理命令行参数
optparse, 功能强大, 易于使用, 可以方便地生成标准的, 符合 Unix/Posix 规范的命令行说明.(Python2.7 以后弃用, 不会继续发展)
argparse, 使其更加容易的编写用户友好的命令行接口. 它所需的程序进程了参数定义, argparse 将更好的解析 sys.argv. 同时 argparse 模块还能自动生成帮助及用户输入错误参数时的提示信息.
很多初学者可能会使用 getopt, 上手简单功能也简单. 比如说 optget 无法解析一个参数多个值的情况, 如 --file file1 file2 file3, 而 optparse 实际上我没有用过, 但是考虑到它在 Python2.7 后已经不再维护, 我们通常也不会使用它.
接下来只剩下 argparse 这一神器, 它几乎能满足我对命令解析器的所有需求. 它支持解析一参数多值, 可以自动生成 help 命令和帮助文档, 支持子解析器, 支持限制参数取值范围等等功能.
0. HelloWorld
不管学习什么东西, 首先第一步都应该是掌握它的大体框架.
而 使用 argparse 前, 框架很简单, 你只需要记住这三行.
- # mytest.py
- import argparse
- parser = argparse.ArgumentParser(description="used for test")
- args = parser.parse_args()
现在可以尝试一下
- [root@localhost ~]# python mytest.py -h
- usage: mytest.py [-h]
- used for test
- optional arguments:
- -h, --help show this help message and exit
- [root@localhost ~]#
- [root@localhost ~]#
- [root@localhost ~]# python mytest.py
- [root@localhost ~]#
已经可以使用了.
1. 入门配置
这里先讲一下, 比较常用的参数配置.
调试: debug
版本号: version
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument('--version', '-v', action='version',
- version='%(prog)s version : v 0.01', help='show the version')
- parser.add_argument('--debug', '-d', action='store_true',
- help='show the version',
- default=False)
- args = parser.parse_args()
- print("=== end ===")
上面 debug 处的配置, 需要讲一下的是 action='store_true' 和 default = False 的作用和区别
store_true: 一旦指定了 -d 或者 --debug , 其值就为 True,store_false 则相反
default=False: 未指定 -d 或者 --debug, 其值就默认为 False
当我们执行 python mytest.py -v, 就会打印 version 里的内容.
- [root@localhost ~]# python mytest.py -v
- mytest.py version : v 0.01
- [root@localhost ~]#
一旦执行时, 指定了参数 -v , 执行到 parser.parse_args() 就会退出程序, 不会打印最后的 === end ===
2. 参数种类
参数可分为 必选参数 (positional arguments) 和 可选参数 (optional arguments).
在 argsparse 里如何实现呢?
必选参数
用单词做参数, 默认就为必选参数
- # mytest.py
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument("name")
- args = parser.parse_args()
- print(args.name)
不指定 name 参数运行一下: python mytest.py
- [root@localhost ~]# python mytest.py
- usage: mytest.py [-h] name
- mytest.py: error: too few arguments
- [root@localhost ~]#
如预期一样, 报错了, 说缺少参数. 那我们指定一下: python mytest.py name wangbm
- [root@localhost ~]# python mytest.py wangbm
- wangbm
- [root@localhost ~]#
可选参数
有两种方式:
单下划线 - 来指定的短参数, 如 - h;
双下划线 -- 来指定的长参数, 如 --help
- # mytest.py
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument("-v", "--verbosity", help="increase output verbosity")
- args = parser.parse_args()
- if args.verbosity:
- print("verbosity turned on")
- else:
- print("verbosity turned off")
试着运行一下 python mytest.py, 不会报错.
- [root@localhost ~]# python mytest.py
- verbosity turned off
- [root@localhost ~]#
3. 参数类型
有的参数, 是字符串, 有的参数, 是数值.
为了对命令行中的参数进行有效的约束, 我们可以事先对参数的类型进行声明. argparse 会对参数进行校验, 不通过时, 会直接抛出错误.
- # mytest.py
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument("name")
- parser.add_argument("age", type=int)
- args = parser.parse_args()
- print(args.name)
- print(args.age)
测试一下唄.
- [root@localhost ~]# python mytest.py wangbm eighteen
- usage: mytest.py [-h] name age
- mytest.py: error: argument age: invalid int value: 'eighteen'
- [root@localhost ~]#
- [root@localhost ~]# python mytest.py wangbm 18
- wangbm
- 18
- [root@localhost ~]#
你看, 写 eighteen 就不行, 提示类型不合法, 只有写 18 才行.
4. 互斥参数
有些参数, 是互斥的, 有你无我. 比如, 性别.
在 argparse 中如何实现?
- import argparse
- parser = argparse.ArgumentParser()
- group = parser.add_mutually_exclusive_group()
- group.add_argument("-m", "--male", action="store_true")
- group.add_argument("-f", "--female", action="store_true")
- args = parser.parse_args()
如果同时指定了这两个参数, 就会报错.
- [root@localhost ~]# python mytest.py -f
- [root@localhost ~]# python mytest.py -m
- [root@localhost ~]# python mytest.py -m -f
- usage: mytest.py [-h] [-m | -f]
- mytest.py: error: argument -f/--female: not allowed with argument -m/--male
- [root@localhost ~]#
5. 可选值
如果是性别, 可以像上面那样放在两个参数里然后用互斥组来约束, 也可以放在一个参数里, 在 argparse 里限制再在外层做判断.
- # mytest.py
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument("-g", "--gender", default='male',
- choices=['male', 'female'])
- args = parser.parse_args()
- print(args.gender)
试着执行一下, 发现性别只能是男或女, 不能为人妖.
- [root@localhost ~]# python mytest.py --gender male
- male
- [root@localhost ~]# python mytest.py --gender female
- female
- [root@localhost ~]#
- [root@localhost ~]#
- [root@localhost ~]# python mytest.py --gender other
- usage: mytest.py [-h] [-g {
- male,female
- }]
- mytest.py: error: argument -g/--gender: invalid choice: 'other' (choose from 'male', 'female')
- [root@localhost ~]#
6. 指定文件
经常会有那种要在脚本中指定配置文件或者其他文件的需求. 可以使用下面的配置
- import argparse
- parser = argparse.ArgumentParser()
- parser.add_argument('--file', '-f', action='append',
- dest='files',
- help=('additional yaml configuration files to use'),
- type=argparse.FileType('rb'))
- args = parser.parse_args()
dest=files, 是说将命令行中,--file 的参数值赋值给变量 files, 你可以用 args.files 访问.
action=append, 由于我们会有指定多个文件的需求, 那就指定多次 --file ,argparse 会将其放在一个 list 里.
type=argparse.FileType('rb'), 既然是指定文件, 那么参数应该为路径, 并指定打开模式为 rb, 如果如果要取得文件内容, 可以用 args.files[0].read()
7. 子解析器
如果你对命令行, 有过足够多的接触, 就会知道有些情况下会有子解析器.
这里我以自己工作中, 碰到的例子来举个例子.
cloud-init --debug single -name mymodule
其中 single 后面是一个子解析器.
- # cloud-init.py
- def main_single(name, args):
- print("name:", name)
- print("args:", args)
- print("I am main_single")
- # 添加一个子解析器
- subparsers = parser.add_subparsers()
- parser_single = subparsers.add_parser('single',help='run a single module')
- # 对 single 子解析器添加 action 函数.
- parser_single.set_defaults(action=('single', main_single))
- # require=True, 是说如果命令行指定了 single 解析器, 就必须带上 --name 的参数.
- parser_single.add_argument("--name", '-n', action="store",
- help="module name to run",
- required=True)
- args = parser.parse_args()
- (name, functor) = args.action
- if name in ["single"]:
- functor(name, args)
执行命令 cloud-init single -name mymodule, 输出如下
- name: single
- args: Namespace(action=('single', <function main_single at 0x0000000003F161E0>), debug=False, file=None, name='mymodule')
- I am main_single
关注公众号, 获取最新干货!
来源: https://www.cnblogs.com/wongbingming/p/10409919.html