argparse是python中官方自带的命令行参数解析标准库,使用它可以方便的定义和获取命令行参数,同时可以输出简单有用的使用信息。
0.1. 在使用之前
在开始之前,你有必要知道argparse的使用场景。首先看下面一段代码
# open.py def open_file(file): f = open(file,'r') print(f.read()) f.close() if __name__ == '__main__': file = './test.txt' open_file(file)
open.py
中只有一个函数,当你运行python open.py
时,他会打开test.txt
文件并打印他的内容。但当你想打开另一个文件test1.txt
时,你需要修改源代码以满足需求。如果我们可以在运行这个python脚本时,比如说这样python open.py test1.txt
,将需要打开的文件路径动态的传递给open_file
函数,那么就可以在不修改源代码的情况下,完成打开任意文件的需求。那么我们就可以使用argparse
来改造我们的代码。
# open.py + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('file', help='一个存在的文件路径') def open_file(file): f = open(file,'r') print(f.read()) f.close() if __name__ == '__main__': - file = './test.txt' + args = parser.parse_args() - open_file(file) + open_file(args.file)
通过上面的改造,我们就可以在运行`python open.py`时在后面加上一个文件路径,由`argparse`捕捉该路径并传递给`open_file`函数,从而满足动态传递参数的需求。
0.2. 快速开始
首先创建一个解析器
import argparse parser = argparse.ArgumentParser()
在创建解析器时,ArgumentParser
可以接受下面这些参数,在平时的使用过程中,prog
、usage
、description
会是你经常使用的参数。
prog
- 程序的名称(默认值:sys.argv[0])usage
- 描述程序用途的字符串(默认值:从添加到解析器的参数生成)description
- 在参数帮助文档之前显示的文本(默认值:无)epilog
- 在参数帮助文档之后显示的文本(默认值:无)parents
- 一个 ArgumentParser 对象的列表,它们的参数也应包含在内formatter_class
- 用于自定义帮助文档输出格式的类(默认值:内置的HelpFormatter
)prefix_chars
- 可选参数的前缀字符集合(默认值:-
)fromfile_prefix_chars
- 当需要从文件中读取其他参数时,用于标识文件名的前缀字符集合(默认值:None)argument_default
- 参数的全局默认值(默认值:None)conflict_handler
- 解决冲突选项的策略(通常是不必要的)add_help
- 为解析器添加一个 -h/--help 选项(默认值:True)allow_abbrev
- 如果缩写是无歧义的,则允许缩写长选项 (默认值:True)
在创建完成了解析器以后,就可以向解析中添加需要解析的参数,这里需要用到的是add_argument
函数。在添加参数之前,你需要了解一下在argparse
中有哪几种参数:
- 可选参数
可选参数在添加参数时,以-
或--
开头。运行时,需要指定参数名,就像下面这样:
# open.py parser.add_argument('-f','--file') # 运行时 # python open.py --file test.txt # 或者 # python open.py -f test.txt
- 位置参数
位置参数在添加参数时,直接添加即可。运行时,不需要指定参数名,但需要按照添加的顺序进行传参。
# open.py parser.add_argument('file') # 运行时 # python open.py test.txt
在知道了参数类型后,我们就可以通过add_argument
向解析器中进行传参,它可以接受下面这些参数:
name or flags
- 一个命名或者一个选项字符串的列表,例如 foo 或 -f, --foo。action
- 当参数在命令行中出现时使用的动作基本类型。nargs
- 命令行参数应当消耗的数目。const
- 被一些 action 和 nargs 选择所需求的常数。default
- 当参数未在命令行中出现并且也不存在于命名空间对象时所产生的值(默认值)。type
- 命令行参数应当被转换成的类型。choices
- 可用的参数的容器。required
- 此命令行选项是否必需 (位置参数都是必需的,只有可选参数才需要这个选项且默认为False)。help
- 来对参数进行简单描述。metavar
- 在使用方法消息中使用的参数值示例。dest
- 被添加到 parse_args() 所返回对象上的属性名。
这些参数中,有几个比较难掌握的,下面对他们逐一介绍一下:
- action
action参数是用来确定在传递参数值时,具体的进行的动作。action可以有下面这些取值
store
【默认值】在解析参数时只是默认的将参数添加到parse_args
返回的对象上store_const
需指定const
参数,存储const
对应的值store_true
store_const
在const
为True
的特殊用法store_false
store_const
在const
为False
的特殊用法append
将每个参数存储到一个列表中append_const
将每个const
存储到一个列表中,使用追加的方法count
存储一个参数出现的次数extend
将每个参数存储到一个列表中(和append
很像)
- type
- 传递值应该是一个接受一个参数的函数,并且必须要有一个返回值
- 比如下面这些函数都是支持的
def func(x): return str(x).upper() func2 = lambda x:str(x).lower()
现在,我们正式向解析器中添加参数,我将根据具体的场景来进行讲解,相信这些场景中例子的使用,可以让你快速掌握它。
0.2.1 场景一:加法器一:x+y
通过命令行向程序传递x和y两个参数,然后打印两个值相加的结果
import argparse parser = argparse.ArgumentParser() parser.add_argument('x', type=int, help='x的值') parser.add_argument('y', type=int, help='y的值') args = parser.parse_args() print(args.x + args.y) # python open.py 1 2 # 输出 3
添加完成以后,可以做到将命令行传过来的两个数字绑定到x和y上,同时转换成整型,那么如果传入的两个位置参数不是数字时,程序将会报错(比如python open.py a b
),通过自定义type
函数可以解决这个问题。
def str_to_number(x): try: return int(x): except: return x parser.add_argument('x', type=str_to_number, help='x的值') parser.add_argument('y', type=str_to_number, help='y的值') # python open.py a b # 输出 ab
使用自定义的str_to_number
函数,可以在传入非数字的情况下使得程序继续运行。上面传入的两个参数也可以改写为两个可选参数。
parser.add_argument('-x', type=str_to_number, help='x的值') parser.add_argument('-y', type=str_to_number, help='y的值') # python open.py -x 1 -y 2 # 输出 3 # python open.py -x a -y b # 输出 ab
0.2.2 场景二:开关
通过传递一个参数open
来确定是否打印一个字符串
- 文件名为
test.py
- 传递
open
或o
参数时,打印Hello, world!
- 不传递时,打印
Bybe!
# test.py import argparse parser = argparse.ArgumentParser() # 添加参数 parser.add_argument('-o','--open', action='store_true', help='来控制是否打印', dest='open_btn') args = parser.parse_args() if args.open_btn: print('Hello, world!') else: print('Bybe!') # python test.py --open # 输出结果 Hello, world! # python test.py # 输出结果 Bybe!
这里用到了两个新的参数,action
和dest
。action
指定为store_true
时,可以使得传递参数时,值为True
,不传递时,值就为False
;dest
指定为open_btn
时,可以使用args.open_btn
来获取参数的值。
0.2.3 场景三:加法器二
通过给定一系列数字,最终打印他们的和。
- 文件名为
test.py
- 给定的数字数量未知,但都是整型数字
# test.py import argparse parser = argparse.ArgumentParser() # 添加参数 parser.add_argument('-n','--numbers', type=int, action='append') args = parser.parse_args() print(sum(args.numbers)) # python test.py -n 1 -n 2 -n 3 -n 4 -n 5 # 返回结果 15
这里我们指定了action
为append
,可以使得从命令行传递过来的参数都放到一个列表中,最后可以对列表求和来完成需求。需要将几个整数相加时,就加几个-n
,如果需要相加的参数很多时,那么这种方法简直是反人道的。下面我们使用另一种方法来修改程序:
parser.add_argument('-n','--numbers', type=int, nargs='*') # python test.py -n 1 2 3 4 5 # 返回结果 15
这里通过赋值nargs
参数为*
可以使得-n
后面的一个或多个数字放到一个列表中,这样就不需要每增加一个数字就增加一个-n
,整个过程是自动的。nargs
的值可以是下面这些:
- 数字:比如1 2 3
*
消耗后面零个或多个+
消耗后面一个或多个(后面如果不跟值会报错)?
传参会消耗后面一个值
0.2.4 场景五:投票
有三位候选人,需要将票投给三位中的一位
- 三位候选人分别是A、B和C
- 投票只能投给三位中的一位
- 打印出最终将票投给了谁
# test.py import argparse parser = argparse.ArgumentParser() # 添加参数 parser.add_argument('-v','--vote', choices=['A','B','C'], required=True) args = parser.parse_args() print('把票投给了:' + args.vote) # python test.py -v A # 把票投给了:A # python test.py -v D # 报错了...
这里通过添加choices
参数,同时赋值['A','B','C']
,将命令行传递的参数值限定在了choices
之内,传递任何choices
之外的值都会报错,并且设置了required
的值为True
,就要求这个可选参数是必须要进行传递的。
0.3. 下一步
下一步我打算写一篇argparse
源码相关的文章,带你深入argparse
实现原理和更高阶的使用方法。欢迎后台留言,让我知道你想看的。