冰冻三尺,非一日之寒
和shell
脚本一样,Python
也可以实现脚本传参,其中一个比较简单的方式就是使用argparse
模块来实现的。
基本使用格式
import argparse
parser = argparse.ArgumentParser()
parser.add_argument()
args = parser.parse_args()
首先导入argparse
模块,然后构建创建一个对象来存储输入的参数,再通过add_argument()
方法来添加参数,最后用parse_args()
方法将parser
对象进行解析。
PART1:
ArgumentParser()
基本使用格式:
argparse.ArgumentParser(
prog=None,
usage=None,
description=None,
epilog=None,
parents=[],
formatter_class=<class 'argparse.HelpFormatter'>,
prefix_chars='-',
fromfile_prefix_chars=None,
argument_default=None,
conflict_handler='error',
add_help=True,
allow_abbrev=True,
)
-
prog
:程序名称,默认为sys.argv[0]
。 -
usage
:使用方法,默认会从你的参数自动生成,可不指定。 -
description
:程序描述性文档,该部分会显示使用方法和帮助信息之间。 -
epilog
:程序描述性文档,该部分会显示在参数描述之后。 -
parents
:其它的parser
对象,添加到这里就会自动在该程序中添加其中的参数。 -
formatter_class
:打印帮助信息的风格(class)。 -
prefix_chars
:可选参数前缀,默认是“ - ”。 -
argument_default
:所有参数的默认值。 -
add_help
:是否添加帮助信息,默认为True
。
下面进行详细的说明:
- 首先说明前四个参数:
#!/usr/bin/python3
#test.py
import argparse
parser = argparse.ArgumentParser(prog = "test.py",
description = "This is a test python script.",
epilog = "This is an additional line.")
parser.add_argument("--print", "-p", type = str, default = "NONE", help = "str to print.")
args = parser.parse_args()
print(args.print)
在命令行中进行调用:
chmod +x test.py
./test.py --help
usage: test.py [-h] [--print PRINT]
This is a test python script.
optional arguments:
-h, --help show this help message and exit
--print PRINT, -p PRINT
str to print.
This is an additional line.
可以看到:
(1)description
参数的内容显示在使用方法和帮助信息之间;
(2)epilog
参数的内容显示在参数描述之后;
(3)usage
不需要你指定,会自动根据你的参数来进行组织。
- 再说明
parents
参数:
parents
参数能够继承其它参数存储对象的内容,例如下面这段代码:
#!/usr/bin/python3
#test1.py
import argparse
parent_parser = argparse.ArgumentParser(add_help = False)
parent_parser.add_argument("--parentprint", "-t", type = str, default = "NONE", help = "str to print.")
parser = argparse.ArgumentParser(prog = "test.py",
description = "This is a test python script.",
epilog = "This is an additional line.",
parents = [parent_parser])
parser.add_argument("--print", "-p", type = str, default = "NONE", help = "str to print.")
args = parser.parse_args()
print(args.print)
在命令行中调用:
./test1.py --help
usage: test.py [-h] [--parentprint PARENTPRINT] [--print PRINT]
This is a test python script.
optional arguments:
-h, --help show this help message and exit
--parentprint PARENTPRINT, -t PARENTPRINT
str to print.
--print PRINT, -p PRINT
str to print.
This is an additional line.
这里的--parentprint
参数是由“父对象”parent_parser
传递给“子对象”parser
的。需要强调的是:parent_parser
需要添加add_help=False
参数,这是因为add_help
默认为True
,如果不设置,有关--help
的信息会在结果中打印两遍。
- 最后,解释一下
formatter_class
参数:
具体来说,这个参数是控制帮助信息打印的格式,一般来说即使我们在description
和epilog
中进行换行,最终打印出来的信息还是会在一行中,那么formatter_class
参数就能让你完全自定义打印的格式,例如下面这段代码:
#!/usr/bin/python3
#test2.py
import textwrap #pay attention here
import argparse
parser = argparse.ArgumentParser(prog = "test.py",
description =textwrap.dedent('''\
This is a
test python script.
'''),
epilog = "This is an additional line.",
formatter_class = argparse.RawDescriptionHelpFormatter)
parser.add_argument("--print", "-p", type = str, default = "NONE", help = "str to print.")
args = parser.parse_args()
print(args.print)
在命令行中调用:
./test2.py --help
usage: test.py [-h] [--print PRINT]
This is a
test python script.
optional arguments:
-h, --help show this help message and exit
--print PRINT, -p PRINT
str to print.
This is an additional line.
可以看到 This is a test python script 成功实现了换行。
formatter_class
可选的取值:
argparse.RawDescriptionHelpFormatter
argparse.RawTextHelpFormatter
argparse.ArgumentDefaultsHelpFormatter
argparse.MetavarTypeHelpFormatter
argparse.RawDescriptionHelpFormatter
能够同时控制description
和epilog
部分的格式,完全按照用户输入格式进行输出;argparse.RawTextHelpFormatter
用于控制整个帮助文档的格式;argparse.ArgumentDefaultsHelpFormatter
用于在每个选项参数的描述中添加默认值,即default
值;argparse.MetavarTypeHelpFormatter
用于在参数中添加type
信息。
PART2:
add_argument()
这个部分的内容一般会有:
-
(1)
name
orflag
该参数你可以简单理解为就是给传入的参数取了一个名字,可以是可选参数,也可以是位置参数,其中可选参数一般前面会有一个短横线“-”,这也是python识别可选参数的方法。
例如:创建可选参数的方法为parser.add_argument('-f', '--foo')
,而位置参数则不需要短横线:parser.add_argument('bar')
。一般来说位置参数是必选的,什么是位置参数,可以简单理解为根据位置信息传入的参数,举一个最简单的例子:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('bar')
args = parser.parse_args()
print(args.bar)
命令行调用:
./test.py --help
usage: test.py [-h] bar
positional arguments:
bar
optional arguments:
-h, --help show this help message and exit
./test.py hello
hello
-
(2)
action
当我们把参数读取进来了之后该怎么处理呢?这就是由action
来决定的,action
可能的取值有:store
,store_const
,store_true
,store_false
,append
,append_const
,count
,help
,version
,extend
。
逐个部分介绍,最后将会有一个综合实例进行解释:
~ store
:这是默认操作,就是简单存储参数的值;
~ store_const
:表示一旦有这个name
或flag
,则将其存储为某个定值,当action='store_const'
时,就必须同时有const=
的参数;
~ store_true
与store_false
:表示一旦有这个name
或flag
,则将其存储为布尔变量ture
(对store_true
来说)和false
(对store_false
来说),相应的没有这个name
或flag
时,则将其存储为布尔变量false
(对store_true
来说)和true
(对store_false
来说);
~ append
:将传入的参数存储到列表当中,这个选项尤其适用于一个name
或flag
会出现多次的情况;
~ append_const
:当有这个name
或flag
时,将其存储为定值并放在列表里;
~ count
:计算一个name
或flag
出现的次数;
~ help
:打印帮助信息的,默认添加了,不用管;
~ version
:打印版本信息。
实例(append_const
后面再说):
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', action = 'store')
parser.add_argument('-b', action = 'store_const', const = 100)
parser.add_argument('-c', action = 'store_true')
parser.add_argument('-d', action = 'store_false')
parser.add_argument('-e', action = 'append')
parser.add_argument('-i', action = 'count')
parser.add_argument('-v', action = 'version', version='%(prog)s 1.0.0')
args = parser.parse_args()
print(args.a)
print(args.b)
print(args.c)
print(args.d)
print(args.e)
print(args.i)
下面来进行命令行调用,分别看输出结果:
./test.py -v
#test.py 1.0.0
./test.py -a store -b -c -d -e 1 -e 3 -iiii
#store 输入的就是'store'字符串,直接简单保存
#100 只要有'-b'这个name,就存储为一个定值const = 100
#True 只要有'-c'这个name,就存储为一个布尔变量True
#False 只要有'-d'这个name,就存储为一个布尔变量False
#['1', '3'] 将通过'-e'传入的参数存储在列表中
#4 i出现了四次
再换种方式来调用:
./test.py
#None 没输入任何东西,所以是none
#None 没有'-b',所以时none
#False 没有'-c',所以是False
#True 没有'-d',所以是True
#None 没有'-e',所以是none
#None 没有-i,所以是none
当然你也可以通过default
来指定默认的值,而不是None:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', action = 'store', default = '***')
parser.add_argument('-b', action = 'store_const', const = 100)
parser.add_argument('-c', action = 'store_true')
parser.add_argument('-d', action = 'store_false')
parser.add_argument('-e', action = 'append')
parser.add_argument('-i', action = 'count', default = 10000)
parser.add_argument('-v', action = 'version', version='%(prog)s 1.0.0')
args = parser.parse_args()
print(args.a)
print(args.b)
print(args.c)
print(args.d)
print(args.e)
print(args.i)
调用:
./test.py
#***
#None
#False
#True
#None
#10000
-
(3)
nargs
注意到我们前面的传参都是单个命令行参数,也就是说没有办法在一个name
或flag
后面传入两个及以上的参数,nargs
正是为了解决这个问题。我们可以通过nargs
来指定改name
或flag
后可传入的参数的个数,并将其存储在一个列表里面,即便只有一个参数(指定nargs = 1
)。
#!/data01/skm/miniconda3/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', nargs = 2)
parser.add_argument('-b', nargs = 1)
args = parser.parse_args()
print(args.a)
print(args.b)
调用:
./test.py -a 1 2 -b c
#['1', '2']
#['d']
此外,有时我们会把nargs
指定为?
,而不是一个整数,这是因为有时候我们传入的参数可能只有一个也可能一个都没有,此时我们可以指定其为?
,**需要解释的是,对于可选参数来说,我们可以同时添加const
和default
:当没有name
或flag
时,会使用default
的值;而当有name
或flag
而没有命令行参数时,就会使用const
的值。
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', nargs = 2)
parser.add_argument('-b', nargs = 1)
parser.add_argument('-c', nargs = '?', default = 1, const = 2)
args = parser.parse_args()
print(args.a)
print(args.b)
print(args.c)
命令行调用:
./test.py -a 1 2 -b yes -c
#['1', '2']
#['yes']
#2
./test.py -a 1 2 -b yes
#['1', '2']
#['yes']
#1
./test.py -a 1 2 -b yes -c 3
#['1', '2']
#['yes']
#3
注意:不要认为?
可以添加多个参数,实际上只能有一个或没有。
nargs
还有*
和+
两个可能的值,这主要适用于当我们有多个参数(大于3)需要传递时,会将参数存储在列表里面。
-
const
前面已经介绍,不再赘述。但是需要强调的是,使用const
的情况只有两种:
(1)你的action
类型为store_const
或append_const
;
(2)指明了nargs='?'
。
否则你会收到报错。
-
default
以可选参数为例,如果对其添加了default
,当你在调用程序不写该name
或flag
时,程序就会使用你的默认值:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', default = 2)
args = parser.parse_args()
print(args.a)
命令行调用:
./test.py -a 3
#3
./test.py
#2
-
type
默认情况下,程序会认为你所传递的参数都是字符串。而有的时候你会需要诸如浮点数,整数等数据类型,这个时候你需要使用type
来辅助程序确定你所输入的参数的数据类型:
parser.add_argument('-a', type = 'int')
parser.add_argument('-b', type = 'float')
-
choices
相较之于前面的完全自定义输入参数,有时你可能需要用户在你设置的可选列表里面选择合适的参数进行输入:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', choices = [1, 2, 3])
args = parser.parse_args()
print(args.a)
命令行调用:
./test.py --help
#usage: test.py [-h] [-a {1,2,3}]
#optional arguments:
# -h, --help show this help message and exit
# -a {1,2,3}
./test.py -a 4
#usage: test.py [-h] [-a {1,2,3}]
#test.py: error: argument -a: invalid choice: '4' (choose from 1, 2, 3)
可以看到我们必须在1,2,3中选择一个数来作为我们的输入才可以。
-
required
前面提到位置参数时必须的,而带有短横线的为可选参数,但我们常在编写python脚本时通常不会使用位置参数来作为必选参数,我们可以通过required=True
来将其变为一个必选参数。
-
help
通过help
可以为每个参数提供帮助描述信息,同时它也支持一些特殊化的显示,诸如%(prog)s
,%(default)s
以及%(type)s
等:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', choices = [1, 2, 3], default = 1, help = 'the choices to %(prog)s. (default: %(default)s)')
args = parser.parse_args()
print(args.a)
命令行调用:
./test.py --help
#usage: test.py [-h] [-a {1,2,3}]
#optional arguments:
# -h, --help show this help message and exit
# -a {1,2,3} the choices to test.py. (default: 1)
-
metavar
注意到我们前面打印帮助信息时,每个参数后面都会有一串文字:
usage: test.py [-h] [-a AB]
optional arguments:
-h, --help show this help message and exit
-a AB, --ab AB the choices to test.py. (default: None)
例如这里的AB,而metavar
就是用来自定义这部分文字的:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', '--ab', help = 'the choices to %(prog)s. (default: %(default)s)', metavar = 'choice')
args = parser.parse_args()
print(args.a)
命令行调用:
./test.py --help
#usage: test.py [-h] [-a choice]
#optional arguments:
# -h, --help show this help message and exit
# -a choice, --ab choice
# the choices to test.py. (default: None)
可以看到AB已经变成choice了。
-
dest
前面的示例当中我们最终取参数都是用的args.a
这种形式,也就是和name
或flag
保持了一致。但是我们可以用dest
来指定参数传入后的存储变量名称,这时就可以以append_const
为例了:
#!/usr/bin/python
import argparse
parser = argparse.ArgumentParser(prog = 'test.py')
parser.add_argument('-a', const = 1, dest = 'choice', action = 'append_const')
parser.add_argument('-b', const = 2, dest = 'choice', action = "append_const")
args = parser.parse_args()
print(args.choice)
我们将-a
和-b
传入的参数最终都存储在了choice
变量里面,所以最终应该会产生如下结果:
./test.py -a -b
#[1, 2]
Reference: https://docs.python.org/3/library/argparse.html#
网友评论