看完这篇,你可就真的会了argparse!!!

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 看完这篇,你可就真的会了argparse!!!

argparse是python中官方自带的命令行参数解析标准库,使用它可以方便的定义和获取命令行参数,同时可以输出简单有用的使用信息。

0.1. 在使用之前

在开始之前,你有必要知道argparse的使用场景。首先看下面一段代码

# open.py
def open_file(file):
  f = open(file,'r')
  print(f.read())
  f.close()
if __name__ == '__main__':
    file = './test.txt'
    open_file(file)

open.py中只有一个函数,当你运行python open.py时,他会打开test.txt文件并打印他的内容。但当你想打开另一个文件test1.txt时,你需要修改源代码以满足需求。如果我们可以在运行这个python脚本时,比如说这样python open.py test1.txt,将需要打开的文件路径动态的传递给open_file函数,那么就可以在不修改源代码的情况下,完成打开任意文件的需求。那么我们就可以使用argparse来改造我们的代码。

# open.py
+ import argparse
+ parser = argparse.ArgumentParser()
+ parser.add_argument('file', help='一个存在的文件路径')
def open_file(file):
  f = open(file,'r')
  print(f.read())
  f.close()
if __name__ == '__main__':
-    file = './test.txt'
+    args = parser.parse_args()
-    open_file(file)
+    open_file(args.file)
通过上面的改造,我们就可以在运行`python open.py`时在后面加上一个文件路径,由`argparse`捕捉该路径并传递给`open_file`函数,从而满足动态传递参数的需求。

0.2. 快速开始

首先创建一个解析器

import argparse
parser = argparse.ArgumentParser()

在创建解析器时,ArgumentParser可以接受下面这些参数,在平时的使用过程中,progusagedescription会是你经常使用的参数。

  • prog - 程序的名称(默认值:sys.argv[0])
  • usage - 描述程序用途的字符串(默认值:从添加到解析器的参数生成)
  • description - 在参数帮助文档之前显示的文本(默认值:无)
  • epilog - 在参数帮助文档之后显示的文本(默认值:无)
  • parents - 一个 ArgumentParser 对象的列表,它们的参数也应包含在内
  • formatter_class - 用于自定义帮助文档输出格式的类(默认值:内置的HelpFormatter
  • prefix_chars - 可选参数的前缀字符集合(默认值:-
  • fromfile_prefix_chars - 当需要从文件中读取其他参数时,用于标识文件名的前缀字符集合(默认值:None)
  • argument_default - 参数的全局默认值(默认值:None)
  • conflict_handler - 解决冲突选项的策略(通常是不必要的)
  • add_help - 为解析器添加一个 -h/--help 选项(默认值:True)
  • allow_abbrev - 如果缩写是无歧义的,则允许缩写长选项 (默认值:True)

在创建完成了解析器以后,就可以向解析中添加需要解析的参数,这里需要用到的是add_argument函数。在添加参数之前,你需要了解一下在argparse中有哪几种参数:

  1. 可选参数

可选参数在添加参数时,以---开头。运行时,需要指定参数名,就像下面这样:

# open.py
parser.add_argument('-f','--file')
# 运行时
# python open.py --file test.txt
# 或者
# python open.py -f test.txt


  1. 位置参数

位置参数在添加参数时,直接添加即可。运行时,不需要指定参数名,但需要按照添加的顺序进行传参。

# open.py
parser.add_argument('file')
# 运行时
# python open.py test.txt

在知道了参数类型后,我们就可以通过add_argument向解析器中进行传参,它可以接受下面这些参数:

  • name or flags - 一个命名或者一个选项字符串的列表,例如 foo 或 -f, --foo。
  • action - 当参数在命令行中出现时使用的动作基本类型。
  • nargs - 命令行参数应当消耗的数目。
  • const - 被一些 action 和 nargs 选择所需求的常数。
  • default - 当参数未在命令行中出现并且也不存在于命名空间对象时所产生的值(默认值)。
  • type - 命令行参数应当被转换成的类型。
  • choices - 可用的参数的容器。
  • required - 此命令行选项是否必需 (位置参数都是必需的,只有可选参数才需要这个选项且默认为False)。
  • help - 来对参数进行简单描述。
  • metavar - 在使用方法消息中使用的参数值示例。
  • dest - 被添加到 parse_args() 所返回对象上的属性名。

这些参数中,有几个比较难掌握的,下面对他们逐一介绍一下:

  1. action

action参数是用来确定在传递参数值时,具体的进行的动作。action可以有下面这些取值

  • store 【默认值】在解析参数时只是默认的将参数添加到parse_args返回的对象上
  • store_const 需指定const参数,存储const对应的值
  • store_truestore_constconstTrue的特殊用法
  • store_falsestore_constconstFalse的特殊用法
  • append 将每个参数存储到一个列表中
  • append_const 将每个const存储到一个列表中,使用追加的方法
  • count  存储一个参数出现的次数
  • extend  将每个参数存储到一个列表中(和append很像)
  1. type
  • 传递值应该是一个接受一个参数的函数,并且必须要有一个返回值
  • 比如下面这些函数都是支持的
def func(x):
    return str(x).upper()
func2 = lambda x:str(x).lower()

现在,我们正式向解析器中添加参数,我将根据具体的场景来进行讲解,相信这些场景中例子的使用,可以让你快速掌握它。

0.2.1 场景一:加法器一:x+y

通过命令行向程序传递x和y两个参数,然后打印两个值相加的结果

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('x', type=int, help='x的值')
parser.add_argument('y', type=int, help='y的值')
args = parser.parse_args()
print(args.x + args.y)
# python open.py 1 2  
# 输出 3

添加完成以后,可以做到将命令行传过来的两个数字绑定到x和y上,同时转换成整型,那么如果传入的两个位置参数不是数字时,程序将会报错(比如python open.py a b),通过自定义type函数可以解决这个问题。

def str_to_number(x):
    try:
        return int(x):
    except:
        return x
parser.add_argument('x', type=str_to_number, help='x的值')
parser.add_argument('y', type=str_to_number, help='y的值')
# python open.py a b
# 输出 ab

使用自定义的str_to_number函数,可以在传入非数字的情况下使得程序继续运行。上面传入的两个参数也可以改写为两个可选参数。

parser.add_argument('-x', type=str_to_number, help='x的值')
parser.add_argument('-y', type=str_to_number, help='y的值')
# python open.py -x 1 -y 2
# 输出 3
# python open.py -x a -y b
# 输出 ab

0.2.2 场景二:开关

通过传递一个参数open来确定是否打印一个字符串

  • 文件名为test.py
  • 传递openo参数时,打印Hello, world!
  • 不传递时,打印Bybe!
# test.py
import argparse
parser = argparse.ArgumentParser()
# 添加参数
parser.add_argument('-o','--open', action='store_true', help='来控制是否打印', dest='open_btn')
args = parser.parse_args()
if args.open_btn:
    print('Hello, world!')
else:
    print('Bybe!')
# python test.py --open
# 输出结果 Hello, world!
# python test.py
# 输出结果 Bybe!

这里用到了两个新的参数,actiondestaction指定为store_true时,可以使得传递参数时,值为True,不传递时,值就为Falsedest指定为open_btn时,可以使用args.open_btn来获取参数的值。

0.2.3 场景三:加法器二

通过给定一系列数字,最终打印他们的和。

  • 文件名为test.py
  • 给定的数字数量未知,但都是整型数字
# test.py
import argparse
parser = argparse.ArgumentParser()
# 添加参数
parser.add_argument('-n','--numbers', type=int, action='append')
args = parser.parse_args()
print(sum(args.numbers))
# python test.py -n 1 -n 2 -n 3 -n 4 -n 5
# 返回结果 15

这里我们指定了actionappend,可以使得从命令行传递过来的参数都放到一个列表中,最后可以对列表求和来完成需求。需要将几个整数相加时,就加几个-n,如果需要相加的参数很多时,那么这种方法简直是反人道的。下面我们使用另一种方法来修改程序:

parser.add_argument('-n','--numbers', type=int, nargs='*')
# python test.py -n 1 2 3 4 5
# 返回结果 15

这里通过赋值nargs参数为*可以使得-n后面的一个或多个数字放到一个列表中,这样就不需要每增加一个数字就增加一个-n,整个过程是自动的。nargs的值可以是下面这些:

  • 数字:比如1 2 3
  • *  消耗后面零个或多个
  • +  消耗后面一个或多个(后面如果不跟值会报错)
  • ?  传参会消耗后面一个值


0.2.4 场景五:投票

有三位候选人,需要将票投给三位中的一位

  • 三位候选人分别是A、B和C
  • 投票只能投给三位中的一位
  • 打印出最终将票投给了谁
# test.py
import argparse
parser = argparse.ArgumentParser()
# 添加参数
parser.add_argument('-v','--vote', choices=['A','B','C'], required=True)
args = parser.parse_args()
print('把票投给了:' + args.vote)
# python test.py -v A
# 把票投给了:A
# python test.py -v D
# 报错了...

这里通过添加choices参数,同时赋值['A','B','C'],将命令行传递的参数值限定在了choices之内,传递任何choices之外的值都会报错,并且设置了required的值为True,就要求这个可选参数是必须要进行传递的。

0.3. 下一步

下一步我打算写一篇argparse源码相关的文章,带你深入argparse 实现原理和更高阶的使用方法。欢迎后台留言,让我知道你想看的。

相关文章
|
2月前
|
存储 缓存 移动开发
uinapp的setStorageSync和setStorage的区别
uinapp的setStorageSync和setStorage的区别
|
2月前
i++和++i的区别
i++和++i的区别
41 3
|
6月前
|
Dragonfly 安全 数据安全/隐私保护
什么是WPA3?与WPA2有啥区别?
【4月更文挑战第14天】
4812 2
什么是WPA3?与WPA2有啥区别?
|
6月前
|
SQL 安全 Java
myabtis中#{} 和 ${} 的区别是什么
myabtis中#{} 和 ${} 的区别是什么
|
图形学
UnityMainThreadDispatcher.Instance().Enqueue运行原理
UnityMainThreadDispatcher.Instance().Enqueue运行原理
562 1
|
安全 C#
C#委托事件的区别
C#委托事件的区别
164 0
|
C++ Python 容器
C++中pair用法
⭐pair的简介 pair是C++STL(标准模板库)中的一个现有容器,它将2个数据整合成一组数据,当我们类似需求的时候就可以使用到pair啦!pair其实有点像Python中字典中的键值对(Key-Value),一个Key对应着一个Value。pair的本质其实就是个结构体,它含有两个成员变量first和second。因为使用的是struct不是class,所以在定义后是可以直接使用pair中的成员变量的。 其标准库类型–pair类型定义在#include< utility > 头文件中
351 0
categorical_crossentropy与sparse_categorical_crossentropy的区别
categorical_crossentropy与sparse_categorical_crossentropy的区别
|
前端开发 Java API
@RequestParam怎么使用
@RequestParam怎么使用
!与~有什么区别
!与~有什么区别
96 0