其他关于Python的总结文章请访问:https://www.jianshu.com/nb/47435944
在Python中处理命令行参数详解(sys.argv 与 argparse 详解)
在运行python程序的时候,往往需要传入一些参数,本节主要介绍两种设置传入命令行参数的方法。
sys.argv
使用sys.argv
处理传入参数,需要引入sys
模块:
import sys
sys.argv
即是使用命令行运行 python 命令(或者 python3 命令)时获取到的命令行参数数组,它是一个list,包含了python(或者python3)命令后边传入的内容,包括紧跟在 python/python3 后边的第一个脚本的名称,后边其他的参数,如果有的话,则是按照空格来标识不同的参数,即使用空格隔开的元素(不论是整数、字符串、小数等)都视为一个独立的参数,比如如下的程序:
import sys
print(type(sys.argv))
print(len(sys.argv))
print(sys.argv)
我们在命令行中使用如下命令运行该脚本:
python main.py 123 1.5 hello world
就会得到如下的运行结果:
5
['main.py', '123', '1.5', 'hello', 'world']
从结果可以看到,这些参数在sys.argv
中都以字符串的形式存储,所以如果想得到整数、小数等,需要使用 int、float 等进行显式转换:
import sys
a = int(sys.argv[1])
b = int(sys.argv[2])
print(a+b)
调用:
main.py 123 456
就会得到579
的结果。
需要注意的是,脚本名称本身占据了sys.argv[0]
,所以其他传入的参数实际是从sys.argv[1]
开始的。
这种方式虽然简单,但是可用性比较小,必须按照顺序传入参数,而且我们熟悉的 -
和 --
形式的参数是不起作用的:
python main.py --a 123 --b 456
['main.py', '--a', '123', '--b', '456']
所以可以使用下边的功能更加强大、复杂的第二种方法
argparse
argparse
的使用需要引入argparse
包:
import argparse
我们将这种方法称为参数解析器方式,其使用可以分为三个基本步骤:
实例化参数解析器
使用ArgumentParser
实例化一个参数解析器:
parser = argparse.ArgumentParser()
其完整的类的签名如下(可以参考https://docs.python.org/3/library/argparse.html#argumentparser-objects):
class argparse.ArgumentParser(prog=None, usage=None, description=None, epilog=None, parents=[], formatter_class=argparse.HelpFormatter, prefix_chars='-', fromfile_prefix_chars=None, argument_default=None, conflict_handler='error', add_help=True, allow_abbrev=True, exit_on_error=True)
这里列举几个比较重要、常用的参数:
-
description
:一个整体的描述,会显示在帮助文档的前边 -
epilog
:结语,会显示在帮助文档的后边 -
argument_default
:全局设置参数的默认值,默认为None
-
add_help
:为解析器添加一个-h/--help
选项来显示帮助文档,默认值为True
添加参数设置
实例化好一个参数解析器后就开始为其添加参数设置,使用add_argument
方法:正如下边的这行代码,添加了一个 -v
或者 --version
来传入的参数,它的默认值是 1.0
,数据类型是字符串,并且有帮助信息,帮助信息可以在帮助文档中显示。
parser.add_argument('-v', '--version', default='1.0', type=str, help='print the version of the script')
完整的函数签名如下(可以参考https://docs.python.org/3/library/argparse.html#the-add-argument-method):
ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])
其中一些重要且常用的参数列在此处:
- names or flags:简单说就是这个参数的名字,是必须有的参数,排在第一位(如果有多个名字就排在前几位),通常会使用“短格式”或/和“长格式”,短格式也就是使用
-
后边加上一个字母的形式,长格式则是--
后边跟上一个单词的形式,如我们熟知的-v
和--version
。参数在被解析时使用的名字是指-
或--
后边的内容,比如这里的v
和version
。 -
type
:命令行参数应当被转换成的类型,比如bool
、int
、float
、str
等。 -
default
:当参数未在命令行中出现时,使用这个默认值。比如:
在命令行调用时如果没有传入parser.add_argument("--foo", default='1')
-foo
参数,那这个参数的值就会被设置为1 -
help
:对于此项参数的帮助描述,会被打印到帮助文档中。 -
action
:指定该参数的动作,即如何对这个参做哪些处理,可供选择的动作有很多,这里列举一些(完整的以及对于新版的内容可以查看https://docs.python.org/3.9/library/argparse.html#action 以及Action
类的签名:https://docs.python.org/3.9/library/argparse.html#argparse.Action:-
store
:存储参数的值,也是默认的动作,即将从命令行获取的参数存储到对应名称的变量下 -
store_const
:存储一个const
属性的值,使用这个action时通过const
参数指定参数值。(后边会讲到const
)parser.add_argument('--foo', action='store_const', const=42)
-
store_true
和 store_false:是 store_const 的特例,不需要使用const指定参数值,即默认值分别为 True 和 False
parser.add_argument('--foo', action='store_true')
parser.add_argument('--bar', action='store_false') -
append
:存储一个list,对于多次使用一个参数的时候很有用,会将每次使用这个参数获取的值追加的列表中,比如:
此时如果是这样调用命令:parser.add_argument('--foo', action='append')
在解析时,名称python main.py --foo 1 --foo 5.2
foo
对应接收到的值就是一个列表:['1', '5.2']
-
append_const
:和store_const
同理,存储成const
属性的列表,当然也需要const
参数来指定参数值:parser.add_argument('--str', dest='types', action='append_const', const='hello') parser.add_argument('--int', dest='types', action='append_const', const=20)
-
count
: 计算一个关键字参数出现的数目或次数,例如这样设置一个参数:
然后在命令行这样调用该脚本:parser.add_argument('--foo','-f', action='count')
在解析时,名称python main.py --foo --foo --foo
foo
(或者f
)对应的值就是3
特别说明,对于短格式的名称,可以不使用多个-隔开,这样也会被计数:
在解析时,名称python main.py --foo -ffff
foo
(或者f
)对应的值就是5 -
help
:如果一个参数被绑定了这个动作,他的作用就是打印帮助文档,这跟ArgumentParser
中默认的add_help
是完全相同的 -
version
:绑定这个动作后要使用另一个参数version
来指定打印的版本,通常是绑定给--version
或者-v
-
extend
:会将个这个参数后边跟的一个或者多个参数值存储到列表中,他和append
是很相似的但是也有不同,使用extend
,对于一个参数可以跟多个参数值,但是使用append
需要多次调用一个参数,每次跟上一个值,比如这样定义一个参数:
然后这样调用该脚本:parser.add_argument("--foo", action="extend")
在解析时就会将python main.py --foo f1 f2 f3 f4
foo
参数解析成一个list:['f1', 'f2', 'f3', 'f4']
-
-
nargs
- 命令行参数应当消耗的数目,即指定这个参数后边跟的多少个参数值被吸纳到这个参数以及他的action中,可以取的值有:- 一个整数:指定个数,比如:
表示parser.add_argument('--foo', nargs=2)
-foo
后边跟的两个参数值都是它的 -
'?'
:表示如果有一个就要一个参数,如果没有就使用default
指定的值。 -
'*'
:所有能获取的参数,不限个数,包括零个 -
'+'
:和'*'
类似,都是不限个数的参数,但是至少要有一个参数,否则会报错
上述的三个定义可以结合正则表达式来理解,是同样的道理
- 一个整数:指定个数,比如:
-
const
:对于store_const
和append_const
两个动作,这个参数是必须要给出的,它指定了调用这两个动作的时候会将const
所指定的值添加到对象中 -
choices
:这个参数接受一个列表做值,指定所定义的参数能够接受的命令行参数值的范围,比如:
这表示parser.add_argument("--foo", choices=[1, 2, 3], type=int)
-foo
这个参数只能接受1、2、3三个值,如果传入其他值会报错,比如:
就会出现错误:python main.py --foo 4
值得一提的是,如果在使用usage: main.py [-h] [--foo {1,2,3}] main.py: error: argument --foo: invalid choice: 4 (choose from 1, 2, 3)
choices
参数后没有使用default
设置默认值,就会默认使用choices
列表中的第一个值做default
值 -
required
:默认值为False
,如果设置为True
,则表示这个参数必须传入,否则会报错。
解析获取的参数
使用ArgumentParser.parse_args
方法解析获取的参数,返回解析的结果:
args = parser.parse_args()
然后就可以使用设置中对每个参数指定的名字来获取它们的值,比如使用args.foo
获取 --foo
参数获得的值
一个完整的简单的例子
这里有一个简单的例子,同时给出了不同的命令行参数对应的结果
import argparse
parser = argparse.ArgumentParser(description='An argparse example')
parser.add_argument("--method", '-m', choices=['add', 'multiple'], help='choose whether to add or to multiply')
parser.add_argument("--A", '-a', default=1, type=int, help="The first number")
parser.add_argument("--B", '-b', default=2, type=int, help="The second number")
args = parser.parse_args()
if args.method == 'add':
print(args.A + args.B)
else:
print(args.A * args.B)
如下是一些调用的例子:
>python main.py
2
>python main.py --help
usage: main.py [-h] [--method {add,multiple}] [--A A] [--B B]
An argparse example
optional arguments:
-h, --help show this help message and exit
--method {add,multiple}, -m {add,multiple}
choose whether to add or to multiply
--A A, -a A The first number
--B B, -b B The second number
>python main.py --method multiple -a 10 -b 20
200
>python main.py --m add -a 10
12