Python 命令行之旅 —— 深入 argparse (一)
作者:HelloGitHub-Prodesire
HelloGitHub 的《讲解开源项目》系列,项目地址:https://github.com/HelloGitHub-Team/Article
前言
在第一篇“初探 argparse”的文章中,我们初步掌握了使用 argparse
的四部曲,对它有了一个基本的体感。
但是它具体支持哪些类型的参数?这些参数该如何配置?本文将带你深入了解 argparse
的参数们。
本系列文章默认使用 Python 3 作为解释器进行讲解。
若你仍在使用 Python 2,请注意两者之间语法和库的使用差异哦~
参数动作
你是否还记得?在上一篇四部曲中的第二步是定义参数,在这个步骤中,我们指定了 action
入参:
parser.add_argument('--sum', dest='accumulate', action='store_const',
const=sum, default=max,
help='sum the nums (default: find the max)')
那么这里面的 action
,也就是 参数动作
,究竟是用来做什么的呢?
想象一下,当我们在命令行输入一串参数后,对于不同类型的参数是希望做不同的处理的。
那么 参数动作
其实就是告诉解析器,我们希望对应的参数该被如何处理。比如,参数值是该被存成一个值呢,还是追加到一个列表中?是当成布尔的 True 呢,还是 False?
参数动作
被分成了如下 8 个类别:
store
—— 保存参数的值,这是默认的参数动作。它通常用于给一个参数指定值,如指定名字:
>>> parser.add_argument('--name')
>>> parser.parse_args(['--name', 'Eric'])
Namespace(name='Eric')
store_const
—— 保存被const
命名的固定值。当我们想通过是否给定参数来起到标志的作用,给定就取某个值,就可以使用该参数动作,如:
>>> parser.add_argument('--sum', action='store_const', const=sum)
>>> parser.parse_args(['--sum'])
Namespace(sum=<built-in function sum>)
>>> parser.parse_args([])
Namespace(sum=None)
store_true
和store_false
—— 是store_const
的特殊情况,用来分别保存 True 和 False。如果为指定参数,则其默认值分别为 False 和 True,如:
>>> parser.add_argument('--use', action='store_true')
>>> parser.add_argument('--nouse', action='store_false')
>>> parser.parse_args(['--use', '--nouse'])
Namespace(nouse=False, use=True)
>>> parser.parse_args([])
Namespace(nouse=True, use=False)
append
—— 将参数值追加保存到一个列表中。它常常用于命令行中允许多个相同选项,如:
>>> parser.add_argument('--file', action='append')
>>> parser.parse_args(['--file', 'f1', '--file', 'f2'])
Namespace(file=['f1', 'f2'])
append_const
—— 将const
命名的固定值追加保存到一个列表中(const
的默认值为None
)。它常常用于将多个参数所对应的固定值都保存在同一个列表中,相应的需要dest
入参来配合,以放在同一个列表中,如:
不指定 dest
入参,则固定值保存在以参数名命名的变量中
>>> parser.add_argument('--int', action='append_const', const=int)
>>> parser.add_argument('--str', action='append_const', const=str)
>>> parser.parse_args(['--int', '--str'])
Namespace(int=[<class 'int'>], str=[<class 'str'>])
指定 dest
入参,则固定值保存在 dest
命名的变量中
>>> parser.add_argument('--int', dest='types', action='append_const', const=int)
>>> parser.add_argument('--str', dest='types', action='append_const', const=str)
>>> parser.parse_args(['--int', '--str'])
Namespace(types=[<class 'int'>, <class 'str'>])
count
—— 计算参数出现次数,如:
>>> parser.add_argument('--increase', '-i', action='count')
>>> parser.parse_args(['--increas', '--increase'])
Namespace(increase=2)
>>>parser.parse_args(['-iii'])
Namespace(increase=3)
help
—— 打印解析器中所有选项和参数的完整帮助信息,然后退出。version
—— 打印命令行版本,通过指定version
入参来指定版本,调用后退出。如:
>>> parser = argparse.ArgumentParser(prog='CMD')
>>> parser.add_argument('--version', action='version', version='%(prog)s 1.0')
>>> parser.parse_args(['--version'])
CMD 1.0
参数类别
如果说 参数动作
定义了解析器在接收到参数后该如何处理参数,那么 参数类别
就是告诉解析器这个参数的元信息,也就是参数是什么样的。比如,参数是字符串呢?还是布尔类型呢?参数是在几个值中可选的呢?还是可以给定值,等等。
下面,我们将逐一介绍不同类型的参数。
可选参数
可选参数
顾名思义就是参数是可以加上,或不加上。默认情况下,通过 ArgumentParser.add_argument
添加的参数就是可选参数。
我们可以通过 -
来指定短参数,也就是名称短的参数;也可以通过 --
来指定长参数,也就是名称长的参数。当然也可以两个都指定。
可选参数通常用于:用户提供一个参数以及对应值,则使用该值;若不提供,则使用默认值。如:
>>> parser.add_argument('--name', '-n')
>>> parser.parse_args(['--name', 'Eric']) # 通过长参数指定名称
Namespace(name='Eric')
>>> parser.parse_args(['-n', 'Eric']) # 通过短参数指定名称
Namespace(name='Eric')
>>> parser.parse_args([]) # 不指定则默认为 None
Namespace(name=None)
参数类型
参数类型
就是解析器参数值是要作为什么类型去解析,默认情况下是 str
类型。我们可以通过 type
入参来指定参数类型。
argparse
所支持的参数类型多种多样,可以是 int
、float
、bool
等,比如:
>>> parser.add_argument('-i', type=int)
>>> parser.add_argument('-f', type=float)
>>> parser.add_argument('-b', type=bool)
>>> parser.parse_args(['-i', '1', '-f', '2.1', '-b', '0'])
Namespace(b=False, f=2.1, i=1)
更厉害的是,type
入参还可以是可调用(callable
)对象。这就给了我们很大的想象空间,可以指定 type=open
来把参数值作为文件进行处理,也可以指定自定义函数来进行类型检查和类型转换。
作为文件进行处理:
>>> parser.add_argument('--file', type=open)
>>> parser.parse_args(['--file', 'README.md'])
Namespace(b=None, f=None, file=<_io.TextIOWrapper name='README.md' mode='r' encoding='cp936'>, i=None)
使用自定义函数进行处理,入参为参数值,需返回转换后的结果。
比如,对于参数 --num
,我们希望当其值小于 1 时则返回 1,大于 10 时则返回 10:
>>> def limit(string):
... num = int(string)
... if num < 1:
... return 1
... if num > 10:
... return 10
... return num
...
>>> parser.add_argument('--num', type=limit)
>>> parser.parse_args(['--num', '-1']) # num 小于1,则取1
Namespace(num=1)
>>> parser.parse_args(['--num', '15']) # num 大于10,则取10
Namespace(num=10)
>>> parser.parse_args(['--num', '5']) # num 在1和10之间,则取原来的值
Namespace(num=5)
参数默认值
参数默认值
用于在命令行中不传参数值的情况下的默认取值,可通过 default
来指定。如果不指定该值,则参数默认值为 None
。
比如:
>>> parser.add_argument('-i', default=0, type=int)
>>> parser.add_argument('-f', default=3.14, type=float)
>>> parser.add_argument('-b', default=True, type=bool)
>>> parser.parse_args([])
Namespace(b=True, f=3.14, i=0)
位置参数
位置参数
就是通过位置而非是 -
或 --
开头的参数来指定参数值。
比如,我们可以指定两个位置参数 x
和 y
,先添加的 x
位于第一个位置,后加入的 y
位于第二个位置。那么在命令行中输入 1 2
的时候,分别对应到的就是 x
和 y
:
>>> parser.add_argument('x')
>>> parser.add_argument('y')
>>> parser.parse_args(['1', '2'])
Namespace(x='1', y='2')
可选值
可选值
就是限定参数值的内容,通过 choices
入参指定。
有些情况下,我们可能需要限制用户输入参数的内容,只能在预设的几个值中选一个,那么 可选值
就派上了用场。
比如,指定文件读取方式限制为 read-only
和 read-write
:
>>> parser.add_argument('--mode', choices=('read-only', 'read-write'))
>>> parser.parse_args(['--mode', 'read-only'])
Namespace(mode='read-only')
>>> parser.parse_args(['--mode', 'read'])
usage: [-h] [--mode {read-only,read-write}]
: error: argument --mode: invalid choice: 'read' (choose from 'read-only', 'read-write')
互斥参数
互斥参数
就是多个参数之间彼此互斥,不能同时出现。使用互斥参数首先通过 ArgumentParser.add_mutually_exclusive_group
在解析器中添加一个互斥组,然后在这个组里添加参数,那么组内的所有参数都是互斥的。
比如,我们希望通过命令行来告知乘坐的交通工具,要么是汽车,要么是公交,要么是自行车,那么就可以这么写:
>>> group = parser.add_mutually_exclusive_group()
>>> group.add_argument('--car', action='store_true')
>>> group.add_argument('--bus', action='store_true')
>>> group.add_argument('--bike', action='store_true')
>>> parser.parse_args([]) # 什么都不乘坐
Namespace(bike=False, bus=False, car=False)
>>> parser.parse_args(['--bus']) # 乘坐公交
Namespace(bike=False, bus=True, car=False)
>>> parser.parse_args(['--bike']) # 骑自行车
Namespace(bike=True, bus=False, car=False)
>>> parser.parse_args(['--bike', '--car']) # 又想骑车,又想坐车,那是不行的
usage: [-h] [--car | --bus | --bike]
: error: argument --car: not allowed with argument --bike
可变参数列表
可变参数列表
用来定义一个参数可以有多个值,且能通过 nargs
来定义值的个数。
若 nargs=N
,N
为一个数字,则要求该参数提供 N 个值,如:
>>> parser.add_argument('--foo', nargs=2)
>>> print(parser.parse_args(['--foo', 'a', 'b']))
Namespace(foo=['a', 'b'])
>>> print(parser.parse_args(['--foo', 'a', 'b', 'c']))
usage: [-h] [--foo FOO FOO]
: error: unrecognized arguments: c
若 nargs=?
,则要求改参数提供 0 或 1 个值,如:
>>> parser.add_argument('--foo', nargs='?')
>>> parser.parse_args(['--foo'])
Namespace(foo=None)
>>> parser.parse_args(['--foo', 'a'])
Namespace(foo='a')
>>> parser.parse_args(['--foo', 'a', 'b'])
usage: [-h] [--foo [FOO]]
: error: unrecognized arguments: b
若 nargs=*
,则要求改参数提供 0 或多个值,如:
>>> parser.add_argument('--foo', nargs='*')
>>> parser.parse_args(['--foo'])
Namespace(foo=[])
>>> parser.parse_args(['--foo', 'a'])
Namespace(foo=['a'])
>>> parser.parse_args(['--foo', 'a', 'b', 'c', 'd', 'e'])
Namespace(foo=['a', 'b', 'c', 'd', 'e'])
若 nargs=?
,则要求改参数至少提供 1 个值,如:
>>> parser.add_argument('--foo', nargs='+')
>>> parser.parse_args(['--foo', 'a'])
Namespace(foo=['a'])
>>> parser.parse_args(['--foo'])
usage: [-h] [--foo FOO [FOO ...]]
: error: argument --foo: expected at least one argument
小节
在了解了参数动作和参数类别后,是不是渐渐开始对使用 argparse
胸有成竹了呢?至少,用现在学到的知识来完成简单的命令行工具已经不再话下了。
在下一篇文章中,我们来继续深入了解 argparse
的功能,如何修改参数前缀,如何定义参数组,如何定义嵌套的解析器,如何编写自定义动作等,让我们拭目以待吧~
欢迎关注 HelloGitHub 公众号,获取更多开源项目的资料和内容
『讲解开源项目系列』启动——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎联系我们给我们投稿,让更多人爱上开源、贡献开源~
Python 命令行之旅 —— 深入 argparse (一)的更多相关文章
- Python 命令行之旅 —— 初探 argparse
『讲解开源项目系列』启动--让对开源项目感兴趣的人不再畏惧.让开源项目的发起者不再孤单.跟着我们的文章,你会发现编程的乐趣.使用和发现参与开源项目如此简单.欢迎联系我们给我们投稿,让更多人爱上开源.贡 ...
- Python 命令行之旅:深入 argparse(二)
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- Python 命令行之旅:使用 argparse 实现 git 命令
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- python命令行参数解析模块argparse和docopt
http://blog.csdn.net/pipisorry/article/details/53046471 还有其他两个模块实现这一功能,getopt(等同于C语言中的getopt())和弃用的o ...
- Python命令行参数解析模块argparse
当写一个Python脚本时经常会遇到不同参数不同功能的情况,如何做一个更好看的命令帮助信息以及对命令参数解析呢? 这就需要使用argparse模块 #!/usr/bin/env python # -* ...
- Python 命令行参数解析工具 argparse
为什么需要argparse 开门见山,举一个简易计算器代码的例子,其中sys.argv用来读取脚本执行时后面传入的参数. def calculator(x, y, operation): if &qu ...
- Python 命令行之旅:使用 docopt 实现 git 命令
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- Python 命令行之旅:深入 click 之参数篇
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- Python 命令行之旅:深入 click 之选项篇
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
随机推荐
- java算法题每日一练01,java入门简单算法题小练
1.给数组做反序 public class Ak01 { public static void main(String[] args) { int[] a = new int[]{22,48,41,2 ...
- 详叙BeanWrapper和PropertyDescriptor
每篇一句 千古以来要饭的没有要早饭的,知道为什么吗? 相关阅读 [小家Spring]聊聊Spring中的数据转换:Converter.ConversionService.TypeConverter.P ...
- 内核下载、nfs挂载:个性问题及解决方法~~共勉
开发板下载内核遇到starting waiting问题时: 首先想到是下载地址的问题! 将原本下载地址减去0X40,例如:smart210下载地址0X20008000,修改为0X20007FC0,即可 ...
- Excel催化剂开源第13波-VSTO开发之DataGridView控件几个小坑
Excel催化剂内部大量使用了DataGridView,这其中有一些小坑,花了力气才解决的,在此给广大开发者作简单分享. 为何要使用DataGridView而不是其他控件如ListBox.ListVi ...
- 曹工杂谈:手把手带你读懂 JVM 的 gc 日志
一.前言 今天下午本来在划水,突然看到微信联系人那一个红点点,看了下,应该是博客园的朋友.加了后,这位朋友问了我一个问题: 问我,这两块有什么关系? 看到这段 gc 日志,一瞬间脑子还有点懵,嗯,这个 ...
- 深挖Openstack Nova - Scheduler调度策略
深挖Openstack Nova - Scheduler调度策略 一. Scheduler的作用就是在创建实例(instance)时,为实例选择出合适的主机(host).这个过程分两步:过滤(F ...
- linux初学者-mail篇
linux初学者-mail篇 邮件是在生活中比较常用的一个工具,在linux系统中的邮件也是.在linux中,邮件的发送所用的服务时postfix,邮件的接收所用的服务是pop(110端口).ima ...
- 入门训练-1.A+B问题
问题描述 输入A.B,输出A+B. 说明:在“问题描述”这部分,会给出试题的意思,以及所要求的目标. 输入格式 输入的第一行包括两个整数,由空格分隔,分别表示A.B. 说明:“输入格式”是描述在测试你 ...
- 单调栈&单调队列
最近打了三场比赛疯狂碰到单调栈和单调队列的题目,第一,二两场每场各一个单调栈,第三场就碰到单调队列了.于是乎就查各种博客,找单调栈,单调队列的模板题去做,搞着搞着发现其实这两个其实是一回事,只不过利用 ...
- Active Directory域
引言 在 Microsoft® Windows® 2000 Server 操作系统的诸多增强功能中,Microsoft Active Directory™ 功能的引入意义最为重大,但也最常引起困惑.与 ...