python应用的参数管理(1):argparse 模块基本用法

一、说明

在python程序中,一个基本app能够在命令行执行,如何从OS的命令行传递种种不同形式的参数?这需要专门的参数管理,argparse就是这种参数管理类。本篇着重几个方面:1)有效性检测。2)帮助生成。3)参数接口表 4)模块和参数的对应方式。

二、关于argparse的说明

2.1 与*args和**kwarsgs的区别'

在【python参数管理(1)*args和**kwarsgs】文中谈到*args和**kwarsgs,那么argparse与他们有啥区别?

1)*args和**kwarsgs是在应用(app)内部,是函数之间传递参量

2)argparse是应用层的,它介于操作系统和程序内部之间。是操作系统向一个app传递参数的管理方式。

2.2 argparse模块

那么,如何管理? 在开发Python命令行工具时,处理用户输入的参数是基本需求。argparse模块是Python标准库中用于解析命令行参数的推荐工具,它提供了:

• 清晰的参数定义接口

• 自动生成帮助文档

• 类型检查和错误提示

• 子命令支持等高级功能

类似的东西

argparse vs 其他方案

• sys.argv:原始但繁琐,需要手动解析

• getopt:类似C的getopt(),功能有限

• optparse:已弃用,被argparse取代

• click/docopt:第三方库,各有特色

sys.argv 是这样用的:

import sys

print(sys.argv)

三、建立一个python程序

3.1 案例1:程序框架

python 复制代码
# argparse01.py

import  argparse

parser = argparse.ArgumentParser(description='An argument inputs into command line'
)
# param是参数的名字,type是要传入参数的数据类型,help是该参数的提示信息
parser.add_argument( '-p1','--param1', type=str, default='hello', help='parameter1')
parser.add_argument( '-p2','--param2', type=str, default='world', help='parameter2')

# 获得传入的参数
args =  parser.parse_args()
print(args.param1 + ' ' + args.param2)

以上代码解释:

  • 1 带 '-'的参数:是指定在os上运行该程序的参数名称,比如上面定义中

ptthon argparse01.py -p1 xxxx

就是运行程序的时候,将第一个参数赋值为xxxx

  • 2 带'--'的参数:是程序内部该参数的变量名称

在程序内部,获得os侧传入的参数

args = parser.parse_args()

print(args.param1 + ' ' + args.param2)

3.2 案例2:如何用help了解参数框架

python 复制代码
# test.py
import argparse
def main():
    parser = argparse.ArgumentParser(description="Demo of argparse")
    parser.add_argument('-n','--name', default=' Wang')
    parser.add_argument('-y','--year', default='20')
    args = parser.parse_args()
    print(args)
    name = args.name
    year = args.year
    print('Hello {}  {}'.format(name,year))
if __name__ == '__main__':
    main()

此处argparse建立了一个参数中间对象,使得1)在main内部可以看到参数,并访问。2)在调用test.py的时候,也可以操作这些参数。3)而且用halp可以查看这些参数,如图:

3.3 案例3:调用和操作过程

argparse 模块可以让人轻松编写用户友好的命令行接口。程序定义它需要的参数,然后 argparse 将弄清如何从 sys.argv 解析出那些参数。 argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。

调用argparse 模块的操作步骤:

1)创建一个解析器 argparse.ArgumentParser

2)添加参数 parser.add_argument

3)解构参数 args = parser.parse_args()

示例

以下代码是一个 Python 程序,它获取一个整数列表并计算总和或者最大值:

python 复制代码
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',
                    const=sum, default=max,
                    help='sum the integers (default: find the max)')

args = parser.parse_args()
print(args.accumulate(args.integers))

假设上面的 Python 代码保存在名为 prog.py 的文件中,它可以在命令行运行并提供有用的帮助信息:

$ python prog.py -h

usage: prog.py [-h] [--sum] N [N ...]

Process some integers.

positional arguments:

N an integer for the accumulator

optional arguments:

-h, --help show this help message and exit

--sum sum the integers (default: find the max)

当使用适当的参数运行时,它会输出命令行传入整数的总和或者最大值:

$ python prog.py 1 2 3 4

4

$ python prog.py 1 2 3 4

--sum

10

如果传入无效参数,则会报出错误:

$ python prog.py a b

c

usage: prog.py [-h] [--sum] N [N ...]

prog.py: error: argument N: invalid int value: 'a'

以下部分将引导你完成这个示例。

四、介绍ArgumentParser 对象和参数总览

4.1 定义ArgumentParser的参数

复制代码
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)

创建一个新的 ArgumentParser 对象。所有的参数都应当作为关键字参数传入。每个参数在下面都有它更详细的描述,但简而言之,它们是:

  • prog - 程序的名称 (default: sys.argv[0])

  • usage - 描述程序用途的字符串(默认值:从添加到解析器的参数生成)

  • description - Text to display before the argument help (default: none)

  • epilog - Text to display after the argument help (default: none)

  • parents - 一个 ArgumentParser 对象的列表,它们的参数也应包含在内

  • formatter_class - 用于自定义帮助文档输出格式的类

  • prefix_chars - 可选参数的前缀字符集合(默认值: '-')

  • fromfile_prefix_chars - 当需要从文件中读取其他参数时,用于标识文件名的前缀字符集合(默认值: None

  • argument_default - 参数的全局默认值(默认值: None

  • conflict_handler - 解决冲突选项的策略(通常是不必要的)

  • add_help - 为解析器添加一个 -h/--help 选项(默认值: True

  • allow_abbrev - 如果缩写是无歧义的,则允许缩写长选项 (默认值:True

  • exit_on_error - 决定当错误发生时是否让 ArgumentParser 附带错误信息退出。 (默认值: True)

在 3.5 版更改: 增加了 allow_abbrev 参数。

五、ArgumentParser各个参数明细

5.1 程序名称:参数prog用法(重要度***)

默认情况下,ArgumentParser 对象使用 sys.argv[0] 来确定如何在帮助消息中显示程序名称。这一默认值几乎总是可取的,因为它将使帮助消息与从命令行调用此程序的方式相匹配。例如,对于有如下代码的名为 myprogram.py 的文件:

5.1.1 prog的默认值

以下程序没对prog操作, sys.argv[0]就是它的名称

复制代码
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--foo', help='foo help')
args = parser.parse_args()

该程序的帮助信息将显示 myprogram.py 作为程序名称(无论程序从何处被调用):

复制代码
$ python myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]

optional arguments:
 -h, --help  show this help message and exit
 --foo FOO   foo help
$ cd ..
$ python subdir/myprogram.py --help
usage: myprogram.py [-h] [--foo FOO]

optional arguments:
 -h, --help  show this help message and exit
 --foo FOO   foo help

5.1.2 给prog赋值

要更改这样的默认行为,可以使用 prog= 参数为 ArgumentParser 指定另一个值:

复制代码
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.print_help()
usage: myprogram [-h]

optional arguments:
 -h, --help  show this help message and exit

需要注意的是,无论是从 sys.argv[0] 或是从 prog= 参数确定的程序名称,都可以在帮助消息里通过 %(prog)s 格式说明符来引用。

>>>

复制代码
>>> parser = argparse.ArgumentParser(prog='myprogram')
>>> parser.add_argument('--foo', help='foo of the %(prog)s program')
>>> parser.print_help()
usage: myprogram [-h] [--foo FOO]

optional arguments:
 -h, --help  show this help message and exit
 --foo FOO   foo of the myprogram program

5.2 usage 用法 (重要度*)

该参数包含提示或帮助信息。默认情况下,ArgumentParser 根据它包含的参数来构建用法消息:

>>>

>>> parser = argparse.ArgumentParser(prog='PROG')

>>> parser.add_argument('--foo', nargs='?', help='foo help')

>>> parser.add_argument('bar', nargs='+', help='bar help')

>>> parser.print_help()

usage: PROG [-h] [--foo [FOO]] bar [bar ...]

positional arguments:

bar bar help

optional arguments:

-h, --help show this help message and exit

--foo [FOO] foo help

可以通过 usage= 关键字参数覆盖这一默认消息:

>>>

>>> parser = argparse.ArgumentParser(prog='PROG', usage='%(prog)s [options]')

>>> parser.add_argument('--foo', nargs='?', help='foo help')

>>> parser.add_argument('bar', nargs='+', help='bar help')

>>> parser.print_help()

usage: PROG [options]

positional arguments:

bar bar help

optional arguments:

-h, --help show this help message and exit

--foo [FOO] foo help

在用法消息中可以使用 %(prog)s 格式说明符来填入程序名称。

5.3 description(用法)(重要度**)

对程序进行描述的字符串参量。

大多数对 ArgumentParser 构造方法的调用都会使用 description= 关键字参数。 这个参数简要描述这个程序做什么以及怎么做。 在帮助消息中,这个描述会显示在命令行用法字符串和各种参数的帮助消息之间:

>>>

>>> parser = argparse.ArgumentParser(description='A foo that bars')

>>> parser.print_help()

usage: argparse.py [-h]

A foo that bars

optional arguments:

-h, --help show this help message and exit

在默认情况下,description 将被换行以便适应给定的空间。如果想改变这种行为,见 formatter_class 参数。

5.4 epilog用法(重要度*)

对程序进行描述的字符串参量。

一些程序喜欢在 description 参数后显示额外的对程序的描述。这种文字能够通过给 ArgumentParser:: 提供 epilog= 参数而被指定。

>>>

>>> parser = argparse.ArgumentParser(

... description='A foo that bars',

... epilog="And that's how you'd foo a bar")

>>> parser.print_help()

usage: argparse.py [-h]

A foo that bars

optional arguments:

-h, --help show this help message and exit

And that's how you'd foo a bar

和 description 参数一样,epilog= text 在默认情况下会换行,但是这种行为能够被调整通过提供 formatter_class参数给 ArgumentParse.

5.5 parents用法(重要度****)

有些时候,少数解析器会使用同一系列参数。 单个解析器能够通过提供 parents= 参数给 ArgumentParser 而使用相同的参数而不是重复这些参数的定义。parents= 参数使用 ArgumentParser 对象的列表,从它们那里收集所有的位置和可选的行为,然后将这写行为加到正在构建的 ArgumentParser 对象。

>>>

>>> parent_parser = argparse.ArgumentParser(add_help=False)

>>> parent_parser.add_argument('--parent', type=int)

>>> foo_parser = argparse.ArgumentParser(parents=[parent_parser])

>>> foo_parser.add_argument('foo')

>>> foo_parser.parse_args(['--parent', '2', 'XXX'])

Namespace(foo='XXX', parent=2)

>>> bar_parser = argparse.ArgumentParser(parents=[parent_parser])

>>> bar_parser.add_argument('--bar')

>>> bar_parser.parse_args(['--bar', 'YYY'])

Namespace(bar='YYY', parent=None)

请注意大多数父解析器会指定 add_help=False . 否则, ArgumentParse 将会看到两个 -h/--help 选项(一个在父参数中一个在子参数中)并且产生一个错误。

注解: 你在通过 parents= 传递解析器之前必须完全初始化它们。 如果你在子解析器之后改变父解析器,这些改变将不会反映在子解析器上。

5.6 formatter_class用法(重要度***)

ArgumentParser 对象允许通过指定备用格式化类来自定义帮助格式。目前,有四种这样的类。

class argparse.``RawDescriptionHelpFormatter

class argparse.``RawTextHelpFormatter

class argparse.``ArgumentDefaultsHelpFormatter

class argparse.``MetavarTypeHelpFormatter

RawDescriptionHelpFormatterRawTextHelpFormatter 在正文的描述和展示上给与了更多的控制。ArgumentParser 对象会将 descriptionepilog 的文字在命令行中自动换行。

>>>

复制代码
>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     description='''this description
...         was indented weird
...             but that is okay''',
...     epilog='''
...             likewise for this epilog whose whitespace will
...         be cleaned up and whose words will be wrapped
...         across a couple lines''')
>>> parser.print_help()
复制代码
usage: PROG [-h]

this description was indented weird but that is okay

optional arguments:
 -h, --help  show this help message and exit

likewise for this epilog whose whitespace will be cleaned up and whose words
will be wrapped across a couple lines

RawDescriptionHelpFormatterformatter_class= 表示 descriptionepilog 已经被正确的格式化了,不能在命令行中被自动换行:

>>>

复制代码
>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     formatter_class=argparse.RawDescriptionHelpFormatter,
...     description=textwrap.dedent('''\
...         Please do not mess up this text!
...         --------------------------------
...             I have indented it
...             exactly the way
...             I want it
...         '''))
>>> parser.print_help()
usage: PROG [-h]

Please do not mess up this text!
--------------------------------
   I have indented it
   exactly the way
   I want it

optional arguments:
 -h, --help  show this help message and exit

RawTextHelpFormatter 保留所有种类文字的空格,包括参数的描述。然而,多重的新行会被替换成一行。如果你想保留多重的空白行,可以在新行之间加空格。

ArgumentDefaultsHelpFormatter 自动添加默认的值的信息到每一个帮助信息的参数中:

>>>

复制代码
>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
>>> parser.add_argument('--foo', type=int, default=42, help='FOO!')
>>> parser.add_argument('bar', nargs='*', default=[1, 2, 3], help='BAR!')
>>> parser.print_help()
usage: PROG [-h] [--foo FOO] [bar ...]

positional arguments:
 bar         BAR! (default: [1, 2, 3])

optional arguments:
 -h, --help  show this help message and exit
 --foo FOO   FOO! (default: 42)

MetavarTypeHelpFormatter 为它的值在每一个参数中使用 type 的参数名当作它的显示名(而不是使用通常的格式 dest ):

>>>

复制代码
>>> parser = argparse.ArgumentParser(
...     prog='PROG',
...     formatter_class=argparse.MetavarTypeHelpFormatter)
>>> parser.add_argument('--foo', type=int)
>>> parser.add_argument('bar', type=float)
>>> parser.print_help()
usage: PROG [-h] [--foo int] float

positional arguments:
  float

optional arguments:
  -h, --help  show this help message and exit
  --foo int

5.7 prefix_chars(重要度****)

许多命令行会使用 - 当作前缀,比如 -f/--foo。如果解析器需要支持不同的或者额外的字符,比如像 +f 或者 /foo 的选项,可以在参数解析构建器中使用 prefix_chars= 参数。

>>>

复制代码
>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='-+')
>>> parser.add_argument('+f')
>>> parser.add_argument('++bar')
>>> parser.parse_args('+f X ++bar Y'.split())
Namespace(bar='Y', f='X')

prefix_chars= 参数默认使用 '-'。 提供一组不包括 - 的字符将导致 -f/--foo 选项不被允许。

5.8 romfile_prefix_chars(重要度****)

在某些时候,例如在处理一个特别长的参数列表的时候,把参数列表存入一个文件中而不是在命令行中打印出来会更有意义。 如果提供 fromfile_prefix_chars= 参数给 ArgumentParser 构造器,则任何以指定字符打头的参数都将被当作文件来处理,并将被它们包含的参数所替代。 举例来说:

>>>

>>> with open('args.txt', 'w') as fp:

... fp.write('-f\nbar')

>>> parser = argparse.ArgumentParser(fromfile_prefix_chars='@')

>>> parser.add_argument('-f')

>>> parser.parse_args(['-f', 'foo', '@args.txt'])

Namespace(f='bar')

从文件读取的参数在默认情况下必须一个一行(但是可参见 convert_arg_line_to_args())并且它们被视为与命令行上的原始文件引用参数位于同一位置。所以在以上例子中,['-f', 'foo', '@args.txt'] 的表示和 ['-f', 'foo', '-f', 'bar'] 的表示相同。

fromfile_prefix_chars= 参数默认为 None,意味着参数不会被当作文件对待。

5.9 argument_default(重要度****)

一般情况下,参数默认会通过设置一个默认到 add_argument() 或者调用带一组指定键值对的 ArgumentParser.set_defaults() 方法。但是有些时候,为参数指定一个普遍适用的解析器会更有用。这能够通过传输 argument_default= 关键词参数给 ArgumentParser 来完成。举个栗子,要全局禁止在 parse_args() 中创建属性,我们提供 argument_default=SUPPRESS:

复制代码
>>> parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
>>> parser.add_argument('--foo')
>>> parser.add_argument('bar', nargs='?')
>>> parser.parse_args(['--foo', '1', 'BAR'])
Namespace(bar='BAR', foo='1')
>>> parser.parse_args([])
Namespace()

5.10 allow_abbrev(重要度****)

正常情况下,当你向 ArgumentParser 的 parse_args() 方法传入一个参数列表时,它会 recognizes abbreviations。

这个特性可以设置 allow_abbrev 为 False 来关闭:

>>>

>>> parser = argparse.ArgumentParser(prog='PROG', allow_abbrev=False)

>>> parser.add_argument('--foobar', action='store_true')

>>> parser.add_argument('--foonley', action='store_false')

>>> parser.parse_args(['--foon'])

usage: PROG [-h] [--foobar] [--foonley]

PROG: error: unrecognized arguments: --foon

5.11 conflict_handler(重要度****)

ArgumentParser 对象不允许在相同选项字符串下有两种行为。默认情况下, ArgumentParser 对象会产生一个异常如果去创建一个正在使用的选项字符串参数。

>>>

>>> parser = argparse.ArgumentParser(prog='PROG')

>>> parser.add_argument('-f', '--foo', help='old foo help')

>>> parser.add_argument('--foo', help='new foo help')

Traceback (most recent call last):

..

ArgumentError: argument --foo: conflicting option string(s): --foo

有些时候(例如:使用 parents),重写旧的有相同选项字符串的参数会更有用。为了产生这种行为, 'resolve'值可以提供给 ArgumentParser 的 conflict_handler= 参数:

>>>

>>> parser = argparse.ArgumentParser(prog='PROG', conflict_handler='resolve')

>>> parser.add_argument('-f', '--foo', help='old foo help')

>>> parser.add_argument('--foo', help='new foo help')

>>> parser.print_help()

usage: PROG [-h] [-f FOO] [--foo FOO]

optional arguments:

-h, --help show this help message and exit

-f FOO old foo help

--foo FOO new foo help

注意 ArgumentParser 对象只能移除一个行为如果它所有的选项字符串都被重写。所以,在上面的例子中,旧的 -f/--foo 行为 回合 -f 行为保持一样, 因为只有 --foo 选项字符串被重写。

5.12 add_help(重要度****)

默认情况下,ArgumentParser 对象添加一个简单的显示解析器帮助信息的选项。举个栗子,考虑一个名为 myprogram.py 的文件包含如下代码:

import argparse

parser = argparse.ArgumentParser()

parser.add_argument('--foo', help='foo help')

args = parser.parse_args()

如果 -h or --help 在命令行中被提供, 参数解析器帮助信息会打印:

$ python myprogram.py

--help

usage: myprogram.py [-h] [--foo FOO]

optional arguments:

-h, --help show this help message and exit

--foo FOO foo help

有时候可能会需要关闭额外的帮助信息。这可以通过在 ArgumentParser 中设置 add_help= 参数为 False 来实现。

>>>

>>> parser = argparse.ArgumentParser(prog='PROG', add_help=False)

>>> parser.add_argument('--foo', help='foo help')

>>> parser.print_help()

usage: PROG [--foo FOO]

optional arguments:

--foo FOO foo help

帮助选项一般为 -h/--help。如果 prefix_chars= 被指定并且没有包含 - 字符,在这种情况下, -h --help 不是有效的选项。此时, prefix_chars 的第一个字符将用作帮助选项的前缀。

>>>

>>> parser = argparse.ArgumentParser(prog='PROG', prefix_chars='+/')

>>> parser.print_help()

usage: PROG [+h]

optional arguments:

+h, ++help show this help message and exit

5.13 exit_on_error(重要度****)

正常情况下,当你向 ArgumentParser 的 parse_args() 方法传入一个无效的参数列表时,它将会退出并发出错误信息。

如果用户想要手动捕获错误,可通过将 exit_on_error 设为 False 来启用该特性:

>>>

>>> parser = argparse.ArgumentParser(exit_on_error=False)

>>> parser.add_argument('--integers', type=int)

_StoreAction(option_strings=['--integers'], dest='integers', nargs=None, const=None, default=None, type=<class 'int'>, choices=None, help=None, metavar=None)

>>> try:

... parser.parse_args('--integers a'.split())

... except argparse.ArgumentError:

... print('Catching an argumentError')

...

Catching an argumentError

相关推荐
寻寻觅觅☆6 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
YJlio7 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
l1t7 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
青云计划7 小时前
知光项目知文发布模块
java·后端·spring·mybatis
赶路人儿7 小时前
Jsoniter(java版本)使用介绍
java·开发语言
Victor3568 小时前
MongoDB(9)什么是MongoDB的副本集(Replica Set)?
后端
Victor3568 小时前
MongoDB(8)什么是聚合(Aggregation)?
后端
ceclar1238 小时前
C++使用format
开发语言·c++·算法
山塘小鱼儿8 小时前
本地Ollama+Agent+LangGraph+LangSmith运行
python·langchain·ollama·langgraph·langsimth