在python中,通过命令行传入参数可以使用标准库argparse
实现。它的基本用法读者可以参考官网说明,我在这里主要想说明一下如何使用argparse
来传入布尔值。
1、问题复现
一开始,我的方案是这样的:
# scripy.py
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--debug', default=False, type=bool)
args = parser.parse_args()
if __name__ == '__main__':
print('type of debug:', type(args.debug))
print(args.debug)
按照我的设想,可以通过python scripy.py --debug=True
来指定debug
的值为True
;如果不设置,那么该参数默认就是False
。
一般来说,在使用上述代码时不会遇到什么问题,结果也是按照设想进行输出的。然而,这其实是存在一个严重的缺陷的。
为了说明这个缺陷,我先将程序修改一下:
...
parser.add_argument('--debug', default=True, type=bool)
...
即,将debug
的默认值改成了True
。那么,按照原先的设想:如果在命令行指定--debug=False
,那么参数值就应该是False
,如果不指定,则默认是True
。
但事实并非如此:
(base) [root@localhost ~]# python tmp.py --debug=False
type of debug: <class 'bool'>
True
读者会发现,即使指定了--debug=False
,但实际上的值仍为True
!
这是为什么呢?
2、原因分析
要搞清楚这个问题的原因,就需要知道argparse
在处理参数时的逻辑了:它首先会把所传入的参数看成是字符串,然后如果指定了type
,则调用type
对应的对象对字符串进行处理。
按照这个逻辑,在执行python tmp.py --debug=False
时出现上述结果就不难理解了:
- 首先,
debug
的值是一个字符串'False'
而不是内置关键词False
; - 然后,调用了
bool
对象来尝试将'False'
转换为布尔值。
想必读者可以猜到了,字符串'False'
既然是一个非空字符串,那么bool('False')
的返回值当然就是True
了。
3、解决方案
想要解决这个问题,需要用到action
这个参数。
将代码修改如下:
...
parser.add_argument('--debug', action='store_true')
...
从字面意思来理解,action
的意思是说在接收到参数后的操作,store_true
则是指,如果在命令行显式地指定了对应的参数,则该参数值就为True
,否则就是False
。
所以,在调用的时候,--debug
后面就不能再跟参数值了:
(base) [root@localhost ~]# python tmp.py
type of debug: <class 'bool'>
False
(base) [root@localhost ~]# python tmp.py --debug
type of debug: <class 'bool'>
True