Python 中命令行解析模块 argparse 的使用
|字数总计:2.7k|阅读时长:12分钟|阅读量:
熟悉 Linux 命令行的用户享受着对于不同命令指定不同参数的遍历,如 ls
,表示打印当前目录下内容,而使用 ls /home
能够打印目录 /home
下的内容。这增加了 Linux 命令的使用范围,提高了用户体验。同样,在 Python 中也有类似的功能模块,那就是内置模块argparse
, 其不仅能够自定义解析命令行参数(从 sys.argv 中解析这些参数),还能够解析 JSON 文件。本篇所有命令都是在 jupyter 中演示。
基本步骤
使用 argparse
常用步骤:
import argparse
# 导入模块;
parser = argparse.ArgumentParser(prog="工程名", description="自定义描述信息")
# 实例化一个解析器,在 jupyter 中使用 argparse.ArgumentParser?
可查看更详细的参数内容;
parser.add_argument("-x", "--var_x", type=int, help="传入自变量")
# 添加想要解析的命令行(可选)参数 var_x
(例子)及配置,下面会对个配置进行详解。该步骤可重复添加多个不同的参数;
args = parser.parse_args()
# 解析参数;
args.__dict__.update(d)
# 使用字典 d
更新参数;
args.var_x
# 打印或使用某个参数;
命令行调用例子:
1 2
| python main.py --var_x 3
|
上面的步骤中,用户可灵活使用步骤 3 自定义解析参数,下面进行详细解释。
add_argument 配置
在上面步骤 3 中,用户可自定义添加待解析的参数以及该参数的配置,如取值类型、取值范围、默认值、参数帮助信息等。常用的配置如下:
配置项名 |
描述 |
取值 |
name or flags |
一个命令或者一个选项字符串的列表,例如位置参数 var_x 或者可选参数 -f , --foo |
字符串 |
action |
指定如何处理该参数 |
'store' , 'store_const' , 'store_true' , 'append' , 'append_const' , 'count' , 'help' , 'version' |
choices |
将参数取值限制在特定范围内 |
如 [1, 2] 、range(10) 或其他容器对象 |
const |
存储一个常量值 |
|
default |
当参数在命令行为指定值时使用的默认值 |
默认为 None |
dest |
指定结果命名空间(namespace)中使用的属性名称 |
|
help |
参数的帮助信息 |
|
metavar |
参数的备用显示名称,如帮助中所示 |
|
nargs |
参数可以使用的次数 |
int ,'?' ,'*' ,'+' 或 argparse.REMAINDER |
required |
指示参数是必需的还是可选的 |
True 或 False |
type |
自动将参数转换为给定类型 |
int ,float ,argparse.FileType('w') 或 可调用函数 |
name or flags
add_argument()
方法必须知道是否需要可选参数(如 -x
或 --var_x
)或位置参数(如 var_x
)。因此,传递给 add_argument()
的第一个参数必须是一系列标志或一个简单的参数名称。
可选参数创建方法:
1
| parser.add_argument('-x', '--var_x')
|
位置参数创建方法:
1
| parser.add_argument('var_x')
|
可选参数在命令行解析时,必须指定可选参数的名字,位置参数则是按照添加 add_argument
的位置依次赋值,当遇到可选参数时自动跳过。如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("x") parser.add_argument("-z", "--var_z") parser.add_argument("y") return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print("x: ", args.x) print("z: ", args.var_z) print("y: ", args.y)
|
1 2 3 4
| %%bash cd /workspace/hello/ python t.py 1 -z 2 3
|
结果
action
ArgumentParser
对象将命令行参数与动作相关联。这些动作可以做与它们相关联的命令行参数的任何事,尽管大多数动作只是简单的向 parse_args()
返回的对象上添加属性。action
命名参数指定了这个命令行参数应当如何处理。常用的动作有: 'store', 'store_const', 'store_true', 'append', 'append_const', 'count', 'help', 'version', 'extend'
。
这里只针对 store_true
进行演示,其他参见:argparse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-v", "--verbose", action="store_true") return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() if args.verbose: print("long logs") else: print("short logs")
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py --verbose
|
结果
如果不指定,则赋值 false
1 2 3
| %%bash cd /workspace/hello/ python t.py
|
结果
choices
命令行赋值时,只有取值在 choices
中的才通过。例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-x", "--var_x", choices=["0a", "0b", "0c"]) return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print(args.var_x)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py -x 0a
|
结果
如果取值不在 choices 中则报错。
const
不常用
default
有时候,一些参数在命令行赋值时常被忽略,如果这些参数有 default
默认值,则不会导致程序运行中出错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument('-x', "--var_x", default=42) return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print(args.var_x)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py
|
结果
dest
定义参数在代码中的新名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-x", "--var_x", dest="varX") return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print(args.varX)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py -x 3
|
结果
help
显示参数的帮助信息。当用户请求帮助时(在命令行使用 -h
或 --help
的方式)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-x", "--var_x", help="自变量 x 的值") return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print(args.var_x)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py -h
|
结果
1 2 3 4 5 6 7
| usage: t.py [-h] [-x VAR_X]
python argparser
options: -h, --help show this help message and exit -x VAR_X, --var_x VAR_X 自变量 x 的值
|
在 help
一节中可以发现打印的帮助信息,变量名都是大写,使用参数 metavar
可以指定打印时变量名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-x", "--var_x", metavar='var-x') return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print(args.var_x)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py -h
|
结果
1 2 3 4 5 6 7
| usage: t.py [-h] [-x var-x]
python argparser
options: -h, --help show this help message and exit -x var-x, --var_x var-x
|
nargs
在 add_argument()
方法中如果不添加 nargs
参数,则默认在命令行中可选或位置参数的后面值作为参数的取值,如果增加 nargs
,则命令可选或位置参数后的 nargs
个值作为一个列表元素赋值给参数。nargs 支持的值有:
- N # 一个整数
- ‘?’
- ‘+’ # 匹配参数后面至少一个值,可匹配多个值
- ‘*’ # 匹配参数后面至少0个值,可匹配多个值
更多请参考:argparse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-x", "--var_x") parser.add_argument("-t", "--theta", nargs=2) parser.add_argument("-g", "--gamma", nargs=1) return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print("var_x: ", args.var_x) print("theta: ", args.theta) print("gamma: ", args.gamma)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py -x 1 -t 30 60 -g 0.5
|
结果
1 2 3
| var_x: 1 theta: ['30', '60'] gamma: ['0.5']
|
required
通常,argparse
模块会认为 -f
和 --bar
等旗标是指明 可选的 参数,它们总是可以在命令行中被忽略。 要让一个选项成为 必需的,则可以将 True
作为 required=
关键字参数传给 add_argument()
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("-x", "--var_x", required=True) return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print("var_x: ", args.var_x)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py -x 1
|
结果
如果在命令行不指定参数则会报错,即使增加了 default
参数也会报错。
type
默认情况下,解析器会将命令行解析的值作为字符串赋值给参数,通过指定 type 可以将解析为指定类型的值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| %%writefile /workspace/hello/t.py
import argparse
def t(): parser = argparse.ArgumentParser(description="python argparser") parser.add_argument("count", type=int) parser.add_argument("distance", type=float) parser.add_argument("street", type=ascii, help="ascii 码字符") parser.add_argument("code_point", type=ord, help="单个字符") return parser
if __name__ == "__main__": parser = t() args = parser.parse_args() print("count: ", args.count) print("distance: ", args.distance) print("street: ", args.street) print("code_point: ", args.code_point)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py 1 2.0 'a' '天'
|
结果
1 2 3 4
| count: 1 distance: 2.0 street: 'a' code_point: 22825
|
解析 JSON
有时候,一个工程有多个开发人员开发,每个子模块都有自定义的参数,常常将参数记录在 JSON 中,使用时直接从 JSON 中读取参数的取值即可。
读取 JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| %%writefile /workspace/hello/t.py
import argparse import os, json
def parse_json(json_file): parser = argparse.ArgumentParser(description="python argparser") if json_file is not None and os.path.exists(json_file): with open(json_file, 'r') as jf: parser.__dict__.update(json.load(jf)) return parser
if __name__ == "__main__": d = {'a': 1, 'b': 2} json_file = 't.json' with open(json_file, 'w') as jf: json.dump(d, jf) args = parse_json(json_file) print(args) print(args.a) print(args.b)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py
|
结果
1 2 3
| ArgumentParser(prog='t.py', usage=None, description='python argparser', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True) 1 2
|
JSON 更新参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| %%writefile /workspace/hello/t.py
import argparse import json import os
def parse_json(json_file): parser = argparse.ArgumentParser(description="python argparser") if json_file is not None and os.path.exists(json_file): with open(json_file, "r") as jf: parser.__dict__.update(json.load(jf)) return parser
def update_parse(args, json_file): if json_file is not None and os.path.exists(json_file): with open(json_file, "r") as jf: args.__dict__.update(json.load(jf)) return args
if __name__ == "__main__": d1 = {"a": 1, "b": 2} json_file = "t.json" with open(json_file, "w") as jf: json.dump(d1, jf) d2 = {"a": 10, "b": 20} json_file_new = "t-new.json" with open(json_file_new, "w") as jf: json.dump(d2, jf) args = parse_json(json_file) print(args) print(args.a) print(args.b) args = update_parse(args, json_file_new) print(args) print(args.a) print(args.b)
|
运行
1 2 3
| %%bash cd /workspace/hello/ python t.py
|
结果
1 2 3 4 5 6
| ArgumentParser(prog='t.py', usage=None, description='python argparser', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True) 1 2 ArgumentParser(prog='t.py', usage=None, description='python argparser', formatter_class=<class 'argparse.HelpFormatter'>, conflict_handler='error', add_help=True) 10 20
|
注意
- 添加参数时可以用
-
,但是使用该参数时需要替换为 _
,如: 1 2 3 4 5 6 7 8 9
| import argparse
parser = argparse.ArgumentParser(description='test') parser.add_argument('--seed-test', type=int, default=72, help='Random seed.') args = parser.parse_args()
if __name__ == "__main__": print(args) print(args.seed_test)
|
参考文献
- argparse — 命令行选项、参数和子命令解析器
- Argparse 教程
- argparse模块用法实例详解