argparse 模块定义了如何从 sys.argv 解析出参数, 并自动生成帮助和使用手册,以及在用户给程序传入无效参数时报出错误信息。
文章目录
前言:argparse命令行参数解析器,个人认为它除了能统一规划一个程序的输入接口外,于算法或项目本身没有什么实际意义。只是总在别人项目里总是看到使用它,而python恰好也有这个解析器模块,所以就来了解一下,并记录在此。
一、关于argparse模块
最常见的 parser( 解析器),是把程序文本转换成编译器内部的一种叫做“抽象语法树”(AST)的数据结构。在我看来,它用来统一输入的格式,和提示输入参数要求和错误信息。
python自带命令行参数解析器argparser,关于argparse:
- 处理可选参数和位置参数(- handles both optional and positional arguments)
- 产生高度有用的使用信息(- produces highly informative usage messages)
- 支持分派给子解析器的解析器(- supports parsers that dispatch to sub-parsers)
ArgumentParser
对象:包含将命令行解析成 Python 数据类型所需的全部信息;add_argument()
方法: 给一个 ArgumentParser 对象添加程序参数信息;parse_args()
方法: 解析参数.【ArgumentParser 通过 parse_args() 方法解析参数。它将检查命令行,把每个参数转换为适当的类型然后调用相应的操作。】
二、argparse源码:
class ArgumentParser(_AttributeHolder, _ActionsContainer):
"""Object for parsing command line strings into Python objects.
Keyword Arguments关键参数:
- prog -- The name of the program 程序名(default: sys.argv[0])
- usage -- A usage message (default: auto-generated from arguments)
- description -- A description of what the program does描述程序的功能
- epilog -- Text following the argument descriptions参数描述文本
- parents父解析器 -- Parsers whose arguments should be copied into this one
- formatter_class -- HelpFormatter class for printing help messages打印帮助消息
- prefix_chars -- Characters that prefix optional arguments可选前缀字符
- fromfile_prefix_chars -- Characters that prefix files containing为包含某字符的文件添加前缀字符
additional arguments附加参数
- argument_default -- The default value for all arguments所有参数的默认值
- conflict_handler -- String indicating how to handle conflicts指示如何处理冲突的字符串
- add_help -- Add a -h/-help option【是否添加help选项】
- allow_abbrev -- Allow long options to be abbreviated省略 unambiguously
"""
def __init__(self,
prog=None,
usage=None,
description=None,
epilog=None,
parents=[],
formatter_class=HelpFormatter,
prefix_chars='-',
fromfile_prefix_chars=None,
argument_default=None,
conflict_handler='error',
add_help=True,
allow_abbrev=True):
ArgumentParser
继承自_AttributeHolder
和 _ActionsContainer
。
ArgumentParser
模块包含以下公共类:
- ArgumentParser:命令行解析的主要入口点。
- ArgumentError:ArgumentParser对象引发的异常
解析器出现错误时,解析命令行被ArgumentParser捕获并发出作为命令行消息。 - FileType:用于定义要创建的文件类型的工厂。
- Action:解析器动作的基类。通常,通过将诸如“ store_true”或“ append_const”之类的字符串传递给add_argument()的action =参数来选择Action。但是,为了更好地自定义ArgumentParser动作,可以定义Action的子类并将其作为action =参数传递。
- HelpFormatter,RawDescriptionHelpFormatter,RawTextHelpFormatter,ArgumentDefaultsHelpFormatter: 格式化程序类,可以作为formatter_class =参数传递给ArgumentParser构造函数。 HelpFormatter是默认设置,RawDescriptionHelpFormatter和RawTextHelpFormatter告诉解析器不要更改帮助文本的格式,并且ArgumentDefaultsHelpFormatter将有关参数默认值的信息添加到帮助中。
本模块中的所有其他类均被视为实现细节。
(注意,HelpFormatter和RawDescriptionHelpFormatter仅作为对象名称被视为公共名称-格式化程序对象的API为实现详细信息)
__all__ = [
'ArgumentParser',
'ArgumentError',
'ArgumentTypeError',
'FileType',
'HelpFormatter',
'ArgumentDefaultsHelpFormatter',
'RawDescriptionHelpFormatter',
'RawTextHelpFormatter',
'MetavarTypeHelpFormatter',
'Namespace',
'Action',
'ONE_OR_MORE',
'OPTIONAL',
'PARSER',
'REMAINDER',
'SUPPRESS',
'ZERO_OR_MORE',
]
1. 基类Action
Action是有关如何将命令行字符串转换为Python对象的信息的实际操作。
ArgumentParser 对象将命令行参数与动作相关联。这些动作可以做与它们相关联的命令行参数的任何事,尽管大多数动作只是简单的向 parse_args() 返回的对象上添加属性。action 命名参数指定了这个命令行参数应当如何处理。
class Action(_AttributeHolder):
"""Information about how to convert command line strings to Python objects.
ArgumentParser使用动作对象表示从命令行的一个或多个字符串解析单个参数所需的信息。 Action构造函数的关键字参数也是Action实例的所有属性。
Keyword Arguments:
- option_strings -- 与此操作相关联的命令行选项字符串的列表.
- dest -- 用来保存创建的对象的属性的名称
- nargs -- 应该使用的命令行参数的数量。默认情况下,将使用一个参数并产生一个值。其他值包括:
- N (an integer) consumes N arguments (and produces a list)
(一个整数)使用N个参数(并产生一个列表)
- '?' consumes zero or one arguments
- '*' consumes zero or more arguments (and produces a list)
- '+' consumes one or more arguments (and produces a list)
请注意,默认值和nargs = 1之间的区别在于,使用默认值时,将生成单个值,而使用nargs = 1时,将生成包含单个值的列表。
- const -- 如果指定了选项并且选项使用不带任何值的操作,则将产生的值.
- default -- 如果未指定该选项,则默认的值。.
- type -- 接受单个字符串参数并返回转换后值的可调用对象。标准的Python类型str,int,float和complex是此类可调用对象的有用示例。如果为None,则使用str.
- choices -- 可允许的值的容器。 如果不为None,则在将命令行参数转换为适当的类型之后,如果它不是该集合的成员,则将引发异常。
- required -- 如果必须始终在命令行中指定操作,则为true。 这仅对可选的命令行参数有意义。.
- help -- The help string describing the argument.
- metavar -- 带有帮助字符串的选项自变量要使用的名称。 如果为None,则将“目标”值用作名称.
"""
def __init__(self,
option_strings,
dest,
nargs=None,
const=None,
default=None,
type=None,
choices=None,
required=False,
help=None,
metavar=None):
self.option_strings = option_strings
self.dest = dest
self.nargs = nargs
self.const = const
self.default = default
self.type = type
self.choices = choices
self.required = required
self.help = help
self.metavar = metavar
使用时,通过action确定使用Action的哪个子类。_StoreTrueAction,_XXXX等都是Action的子类。
# register actions
self.register('action', None, _StoreAction)
self.register('action', 'store', _StoreAction)
self.register('action', 'store_const', _StoreConstAction)
self.register('action', 'store_true', _StoreTrueAction)
self.register('action', 'store_false', _StoreFalseAction)
self.register('action', 'append', _AppendAction)
self.register('action', 'append_const', _AppendConstAction)
self.register('action', 'count', _CountAction)
self.register('action', 'help', _HelpAction)
self.register('action', 'version', _VersionAction)
self.register('action', 'parsers', _SubParsersAction)
2. add_argument(self, *args, **kwargs)方法
查看add_argument方法前你需要清楚位置参数和命名参数。
虽然它实际长这样:ArgumentParser.add_argument(name or flags...[, action][, nargs][, const][, default][, type][, choices][, required][, help][, metavar][, dest])
*args接收位置参数,**kwargs接收键值对的命名参数。
*args接收的第一个参数,也就是args[0]是当前文件名。所以len(*args)大于等于1,后续参数会按位置匹配给对应形参。
# =======================
# Adding argument actions 添加参数操作
# =======================
def add_argument(self, *args, **kwargs):
"""
add_argument(dest, ..., name=value, ...)
add_argument(option_string, option_string, ..., name=value, ...)
"""
# if no positional args are supplied or only one is supplied and
# it doesn't look like an option string, parse a positional
# argument
chars = self.prefix_chars
if not args or len(args) == 1 and args[0][0] not in chars:
if args and 'dest' in kwargs:
raise ValueError('dest supplied twice for positional argument')
kwargs = self._get_positional_kwargs(*args, **kwargs)
# otherwise, we're adding an optional argument
else:
kwargs = self._get_optional_kwargs(*args, **kwargs)
# if no default was supplied, use the parser-level default
if 'default' not in kwargs:
dest = kwargs['dest']
if dest in self._defaults:
kwargs['default'] = self._defaults[dest]
elif self.argument_default is not None:
kwargs['default'] = self.argument_default
# create the action object, and add it to the parser
action_class = self._pop_action_class(kwargs)
if not callable(action_class):
raise ValueError('unknown action "%s"' % (action_class,))
action = action_class(**kwargs)
# raise an error if the action type is not callable
type_func = self._registry_get('type', action.type, action.type)
if not callable(type_func):
raise ValueError('%r is not callable' % (type_func,))
# raise an error if the metavar does not match the type
if hasattr(self, "_get_formatter"):
try:
self._get_formatter()._format_args(action, None)
except TypeError:
raise ValueError("length of metavar tuple does not match nargs")
return self._add_action(action)
**kwargs对应的键值对的命名参数:是函数调用时,用key=value
形式进行传参的情形。
# create the action object, and add it to the parser
# 创建操作对象,并将其添加到解析器
action_class = self._pop_action_class(kwargs)
if not callable(action_class):
...
action = action_class(**kwargs) # 形参'action'
action = action_class(**kwargs)
action接收了所有形参,所以,所有涉及action取元素的,都表示可以传的形参。意思是所有action.XXX
的XXX就是函数的参数。如果你想找到这类函数def func(*args, **kwargs)
定义的函数需要哪些参数,就需要看定义时,把*args, **kwargs赋值给了谁XX,比如此处的action,就可以搜索xx去定位需要的参数。这只是一种仅供参考的方式,在那些没有给出def _get_kwargs()
的模块里面。本文argparse模块给出了的。直接去找def _get_kwargs()
就好:
def _get_kwargs(self):
names = [
'option_strings',
'dest',
'nargs',
'const',
'default',
'type',
'choices',
'help',
'metavar',
]
使用add_argument()函数的时候,可以传递'option_strings', 'dest', 'nargs', 'const', 'default', 'type', 'choices', 'help', 'metavar'
控制作为项目的输入接口。
二、argparse的使用
1.示例
argparse的使用步骤:
- 创建一个解析器
使用 argparse 的第一步是创建一个 ArgumentParser 对象; - 调用 add_argument() 方法完成添加参数;
- 通过 parse_args() 方法解析参数。
import argparse
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('integers', metavar='N', type=int, nargs='+',
help='an integer for the accumulator')
parser.add_argument('--sum', dest='accumulate',
action='store_const', # action 命名参数指定了这个命令行参数应当如何处理。
const=sum, # add_argument()的const参数用于保存不从命令行中读取但被各种ArgumentParser动作需求的常数值。
default=max, # 为传参时使用的默认值
help='sum the integers (default: find the max)')
parser.add_argument('--data_type', default=32, type=int, choices=[8, 16, 32],
help="Supported data type i.e. 8, 16, 32 bit")
parser.add_argument('--name', type=str, default='label2city',
help='name of the experiment. It decides where to store samples and models')
args = parser.parse_args() # 调用 parse_args()将返回一个具有 integers 和 accumulate 两个属性的对象。
print(args.integers)
print(args.accumulate(args.integers))
print(args.data_type)
print(args.name)
总结
提示:项目中添加命令行参数解析器,看起来输入很统一,并没有实质意义。学了之后,别人加了,不至于看不明白。如果想要添加,让形式上看起来‘高大上’,可以多练习几次,就学会了。
over!
参考文献:
[1]. 命令行参数解析器模块lib。