这是一篇argparse入门级教程,如果您已对argparse有部分了解,这篇博文不适合您,无需在这里浪费时间。
##速查目录:
1.創建對象argparse.ArgumentParser() 有一個description參數對程序進行介紹
2.增加參數parser.add_argument()
3.解析參數parser.parse_args()
4.添加衝突組parser.add_mutually_exclusive_group()
##add_parse_args參數說明
1.-參數縮寫,--參數全稱
2.help 參數說明(string)
3.action (string)可以當一個flag使用
為store_true時會對參數進行bool賦值
為count時,會根據參數個數為其進行int賦值 如-v就是1,-vv就是2等。不指定會None
4.default,在不指定參數時會被賦值,可以和count聯合起來使用
5.type 指定接受的參數類型(該是什麼類型就是什麼類型)
6.choices (list)指定optional argument可選範圍
之所以把它写在前面就是为了让它能起到速查的效果。笔记用的是繁体,我就不修改了,联系前后文差不多也能看懂(也当做锻炼你识别繁体能力的手段)。
进入正题。很多时候,我们需要提供一个很好的命令行接口,简化程序交互的同时,也要方便用户的使用。说的大白话一点,就是程序如何简单优雅地处理命令行参数。
我猜你第一想到的就是sys.argv,虽然不经常使用,但是很清楚它能够解决问题。
编辑脚本代码wowotou.py(这个文件的名字后面说明):
import sys
print(sys.argv)
在当前目录下打开命令行嵌入:python wowotou.py -h hello world
程序返回一个list,而其中的items是命令中“python”之后的所有被分隔开的“参数”。“wowotou.py”是第一个,“-h”是第二个以此类推。
当我们在程序中需要使用这些参数的时候,就可以通过列表取下标的方法来调用参数。例如sys.argv[0],sys.argv[1]等等。
在简单的程序处理中,这种应对方式完全可以胜任。当程序设计稍微一复杂时,这种方式就显得不那么的尽人意。
比如,程序需要接受一个x值,一个y值,加一个半径r值。来求得一个圆的面积(我知道坐标没啥用,在举例子嘛)。
程序中你可能会这样写:
answer = sys.argv[2] * 2 * math.PI
好像没有什么问题呀?的确,但是你认为的正确是理所当然了。
这个程序的成功执行,是在用户必须知道他输入的第一个参数是x的值,第二个参数是y的值等等诸如此类增加记忆负担的词。简单点说,就是你要求用户记住你程序接受参数的顺序,还不能出错。
来看看argparse是怎么优化的吧,学完后,你可能就会放弃sys.argv了。
argparse同样也是标准库,不需要再次下载。
我们将代码清空:
一般情况下,python程序不会对文件之后的任何参数进行处理。当你导入argparse时:
import argparse
parser = argparse.ArgumentParser() //创建解析器对象
parser.parse_args() //解析命令行参数
print("嘿嘿")
(get到两个基础的方法)
首先程序运行wowotou文件就无须多讲了。当我们在其之后多加入一个-h参数的时,输出了一些解释信息,其中的optional arguments(可选参数)解释了-h参数的含义“show this help message and exit”。如果我们将其换为--help,会得到同样的结果。
这里的-h和--help有什么区别呢?emmm,一个是缩写,一个是全写。这里先做了解,我们会慢慢的深入解释。
还有一点,在创建解析器对象的时候,可以添加一个参数description(value为string类型),看单词就能猜个八九不离十(你要是非猜一,那我也没办法),是对参数解释器目标任务的说明。
稍加修改:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.parse_args()
print("嘿嘿")
这时再输入相同的命令,就可以查看到你写的信息了。这对用户来说也是个不错的提示方式吧。
目前为止,在我们只是简单的引入argparse,并对参数进行解析后。程序可以处理的一个可选参数是-h或--help,这是唯一一个不需要指定的可选参数。那如果指定我们的自定义参数呢?
就是速查中的2,使用add_argument()
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("food")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
print(args.food,",嘿嘿")
我们加入了一个指定参数,参数名称为food,对参数的调用可以直接通过解析后的对象使用“.”运算符+变量名来使用。
命令行中python wowotou.py之后的第一个参数会被当做food的值(你可以把命令行里的food修改为任意的值)。在程序代码中我们只是添加了一个名称为food的参数,程序会默认把第一个参数当做food的值。例如第二条命令中,除了给予了一个“food”的字符串外,还多给了一个“wowo”字符串。程序会将“food”赋值给food参数,而wowo并不知道怎么处理,就会报错。
如果这时使用-h查看帮助信息:
你会惊奇的发现,除了optional arguments参数列表外,多了一个positional arguments,其中只有一个参数,就是我们指定的参数food。
第一个点,关于positional arguments的翻译。我习惯性的说成“位置参数”,有些编程书上翻译为“按位实参”。这个名称更多的会出现在函数里。比如function(value1, value2, key=value3)中,value1和value2都被称为positional argument,而key更习惯的称为关键词实参。
第二个点,关于argument和parameter的理解。我们知道,两个词都有参数的意思,区别点在于一般argument指实参,parameter指形参。
说了这么多,也只是为了帮助你理解positional arguments这个词的含义。选择你喜欢的翻译方式吧。
在argparse中,简单说,位置参数就是必须指定(给予)的参数,即在命令行中必须提供的参数。
如果没给,模块就会提示你需要一个值,为名称是food的参数赋值。
从这里引入optional arguments,我们知道-h参数是属于这个类别的,而且它和positional arguments的区别就是,这个参数可给可不给。就像我们直接执行python + 文件名,程序也可以正常运行。而不像food参数,不给就会报错。
下个问题,那,我们如何制定自己的可选参数?
很简单,参数名前加-或者--。(-和--的区别前面已经说明)
稍加修改:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("-w")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
print(",嘿嘿")
这时再打开帮助信息:
自定义的可选参数就被加入到optional arguments的行列中。和-h参数的说明一对比,我们的-w显得特别骨感。再修改:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("-w", "--wowotou", help="a food named wowotou")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
print(",嘿嘿")
对比着,我们也就知道了全称是怎么设计出来的,以及-h后面的"show this help message and exit"的信息是怎么显示出来的了。
到目前为止,我们还没能做出一点能看的东西。别急,先来看add_argument的第一个关键字参数action。
这篇文章中,action只有两个value(string 类型),一个store_true,另一个是count。先来说store_true。
当action为store_true时,会根据命令行中参数的有无来对参数进行bool赋值。
什么意思呢?
比如:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("-w", "--wowotou", help="a food named wowotou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
if args.wowotou:
print("窝窝头,一块钱四个,嘿嘿")
我们对-w参数添加了store_true的action参数。当这个参数为true时,print一条语句,否则什么都不做。
(通过args解析对象调用参数,必须是那个全称的名字,即必须是args.wowotou,而不能是args.w)
不给参数的时候,all is well。
给了-w参数,成功输出,--wowotou同上。
通过这个例子,我们就晓得了store_true的功能了,当命令行中提供了这个可选参数,就会将其置为true,否则置为false。
嘿嘿,好像开始有趣了。继续吧。
我现在不想卖窝窝头了,我想卖大馒头。我们再将food参数加回来:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("food", help="a name of food")
##parser.add_argument("-w", "--wowotou", help="a food named wowotou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
##if args.wowotou:
## print("窝窝头,一块钱四个,嘿嘿")
print(args.food,"一块钱四个,嘿嘿")
我们知道,positional arguments是必须给的,而参数的值,就是你命令行中的值。如上:
给food参数的赋值是大馒头。
到此,我们通过位置参数得到售卖的商品,而用可选参数执行某些操作。
当职位提升后,我就可以制定价格了,比如一块钱一个,一块钱两个等等。
很简单,再添加一个位置参数接收个数。
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("food", help="a name of food")
parser.add_argument("num", help="how many can I buy for one dollar")
##parser.add_argument("-w", "--wowotou", help="a food named wowotou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
##if args.wowotou:
## print("窝窝头,一块钱四个,嘿嘿")
print(args.food,"一块钱",args.num,"个,嘿嘿")
水面风平浪静,一般海底都波涛汹涌。
经理知道你擅自修改数据后,很生气,在程序里面对你的值进行了修改。
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("food", help="a name of food")
parser.add_argument("num", help="how many can I buy for one dollar")
##parser.add_argument("-w", "--wowotou", help="a food named wowotou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
##if args.wowotou:
## print("窝窝头,一块钱四个,嘿嘿")
print(args.food,"一块钱",args.num - 1 ,"个,嘿嘿")
最后在print的时候,将你的args.num减了一个。好像没什么问题吼~
再次执行出错了,原因是程序通过命令行接受的参数类型只有一种类型,就是string。
两种方法解决,得到数据后,对数据进行类型转换。弊端,接收到的string(用户输入的,具有主观性)并不一定能转换成你想要的类型。(比如将“hahaha”转换成int类型)
这时,可以使用一个参数type来指定你想要接受的类型:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("food", help="a name of food")
parser.add_argument("num", type=int, help="how many can I buy for one dollar")
##parser.add_argument("-w", "--wowotou", help="a food named wowotou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
##if args.wowotou:
## print("窝窝头,一块钱四个,嘿嘿")
print(args.food,"一块钱",args.num - 1 ,"个,嘿嘿")
我们在num参数中加入了type参数,来告诉程序,我要的num参数的值是个int类型。这时:
完美执行了。那如果用户给的不是int类型呢?
会告诉你,这是个无效的int值。如此,用户就知道了,我这里需要给个整数。
在你得知经理不满后,主动认错。经理也退让了一步,同意你指定价格,不过要在他规定的范围内。引入下一个参数choices,这个参数的类型是list。
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("food", help="a name of food")
parser.add_argument("-n", "--num", type=int, help="how many can I buy for one dollar", choices=[1,2,3,4])
##parser.add_argument("-w", "--wowotou", help="a food named wowotou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
##if args.wowotou:
## print("窝窝头,一块钱四个,嘿嘿")
print(args.food,"一块钱",args.num,"个,嘿嘿")
我们将num改为可选参数,并加入了choices。现在num参数的给定值,就只能在choices范围里面挑了:
而当你超出范围时,就会警告你,并告诉你范围集。
继续继续。
我们再将程序修改一下,介绍下一个参数,default:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("-f","--food", help="the name of food", default="窝窝头")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
print(args.food,"一块钱四个,嘿嘿")
将food参数修改为optional argument,并加入default参数赋值string类型“窝窝头”。
在不指定-f参数的情况下,会默认赋值“窝窝头”,在给定参数的情况下,会覆盖掉默认参数。
如:
代码中default被赋值了字符串类型的常量,你可以赋值任何你想要类型。甚至是一个函数(如max,min等等)。
致此,还有一个点没有说到,就是action的count行为。我是认为,这个count可以作为一种等级处理。
举个例子,你摆小摊卖窝窝头,有被没收小推车的风险。我们创建一个参数w代表warning。并用count来表示warning的等级。
show code:
import argparse
parser = argparse.ArgumentParser("What are you selling?")
parser.add_argument("-w","--warning", action="count", default=0)
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
print(args.warning)
if args.warning == 0:
print("淡定,没事~")
elif args.warning == 1:
print("我现在内心有点慌。。。")
elif args.warning == 2:
print("时刻准备着---")
else:
print("跑!")
count的行为,会计算命令行中此参数的出现次数,无论是缩写还是全称。(为了便于演示,在执行判断之前,我们把参数值输出一下。)
直接看使用吧:
对比一下,很容易就能理解。
(这里有一个点,需要说明,当action="count"和default=一个整数同时使用的时候。最终参数的值是default的值加上count的计数值。比如你的default=1,在命令行中参数出现次数为1的时候,程序中这个参数的值就是2。如果default是3,那值为4。)
还有一个函数:add_mutually_exclusive_group()
函数名直译就是“添加相互独立组”,这个是干什么用的呢?其实就是限制某些参数同时出现,举个例子,你不能同时卖“窝头”和“馒头”。如果我们用w代表窝头,m代表馒头,那参数w和m不能同时出现。
这个函数就是干这件事用的。
import argparse
parser = argparse.ArgumentParser("What are you selling?")
group = parser.add_mutually_exclusive_group()
##将w和m参数加入到同一个冲突组中
group.add_argument("-w","--wowotou", action="store_true")
group.add_argument("-m", "--mantou", action="store_true")
args = parser.parse_args() #為了方便調用,我們將他賦值給一個變量
if args.wowotou:
print("窝窝头,一块钱四个,嘿嘿")
elif args.mantou:
print("大馒头,一块钱四个,嘿嘿")
使用示例:
在参数w和m同时出现时,就会对你发出警告,m参数不允许和参数w一起出现。
全部的入门内容已经讲述完毕了,剩下最后一个伏笔没有解释。那就是对文件名“wowotou”的含义说明,不过现在看来,已经没那个了。