江湖道

庙堂,江湖,学术!

返回顶部

python常用模块——argparse

有时候,当我们去写一些系统的管理工具,或者是做前期开发中代码的逻辑调试时需要命令行接口,我们可以使用命令行传参的形式去实现。这样便于执行,若需要与其他程序集成,也是一个不错的选择。
本节我们讨论用python如何实现符合UNIX/POSIX标准的命令。首先介绍argpase模块的使用方法,最后通过一个Linux环境上实现文件回收站的示例展示argpases方法的使用。

1. 解析命令行参数模块

python中有3个内建的模块处理命令行参数。
第一个是:getopt,该模块只能处理简单的命令行参数,我们在此不做介绍,感兴趣的同学呢,可以参考官方文档学习:https://docs.python.org/2/library/getopt.html#module-getopt
第二个是:optparse,该模块功能强大,易于是用,可以方便的生成标准的UNIX/POSIX协议格式的命令,但是他被argparse所取代,python2.7之后弃用。
第三个是:argparse,它能更容器的编写标准的,用户友好的命令行接口,argarse能自动生成帮助以及用户参数错误的提示。官方文档:https://docs.python.org/2/library/argparse.html#module-argparse

2. arggarse 介绍

首先以一个例子开始:将参数求和,并将结构答应到文件。

import argparse
import sys

if __name__ == '__main__':
    # eg:将命令行的参数求和,并将结果写入文件。
    parser = argparse.ArgumentParser(
        prog="Anliu",   #项目名字,默认是sys.args[0]
        #usage="",  #用法说明,默认是从参数中自动生成的,例如:Anliu [-h] [--log LOG] int [int ...]
        description='sum the integers at the command line',  #项目描述
        epilog="xxx",  #参数后的文本描述
        parents="",
        #formatter_class="",
        #prefix_chars="re" #可选参数前缀的字符。
        #fromfile_prefix_chars=""
        #argument_default="-r",
        conflict_handler="error", #如何处理冲突的字符串。
        add_help="False",
        allow_abbrev="False"  #容许长选项缩写。
    )
    parser.add_argument(
        'integers', metavar='int', nargs='+', type=int,
        help='an integer to be summed')
    parser.add_argument(
        '--log', default=sys.stdout, type=argparse.FileType('w'),
        help='the file where the sum should be written')
    parser.add_argument(
        "-d", "--deleteMemoryRemain",
    )
    args = parser.parse_args()
    args.log.write('%s' % sum(args.integers))
    args.log.close()

该模块包含的方法解释:

# 命令行解析库
# 此模块是一个受optparse启示的命令行解析库。
#       处理可选择参数和位置参数。
#       生成信息量大的使用消息。
#       支持分配给自解析器的解析。
#
# 这个模块包括的公共方法有:
#       - ArgumentParser --命令行解析的主要入口点。如上面的示例所示,
#                        add_argument()方法用于使用可选参数和位置参数的操作填充解析器。
#                        然后调用parse_args()方法将命令行中的args转换为具有属性的对象。
#
#       - ArgumentError --ArgumentParser对象在解析器操作出错时引发的异常。
#                        解析命令行时引发的错误由ArgumentParser捕获并作为命令行消息发出。
#
#       - FileType --用于定义要创建的文件类型的工厂。
#                        如上例所示,FileType的实例通常作为add_argument()调用的type=参数传递。
#
#       - Action --解析器操作的基类。
#                  通常,通过向add_argument()的action=参数传递“store_true”或“append_const”等字符串来选择操作。
#                  但是,为了更好地定制ArgumentParser操作,可以定义操作的子类并将其作为Action=参数传递。
#       -HelpFormatter、RawDescriptionHelpFormatter、RawTextHelpFormatter、ArgumentDefaultsHelpFormatter
#                --可以作为Formatter\u class=参数传递给ArgumentParser构造函数的格式化程序类。
#                  HelpFormatter是默认值,
#                  RawDescriptionHelpFormatter和RawTextHelpFormatter告诉解析器不要更改帮助文本的格式,
#                  ArgumentDefaultsHelpFormatter将有关参数默认值的信息添加到帮助中。
#       此模块中的所有其他类都被视为实现细节。
#       (还请注意,HelpFormatter和RawDescriptionHelpFormatter仅作为对象名被视为公共的
#           ——formatter对象的API仍然被视为实现细节。)

2.1 argpase 功能

(1) 处理位置参数。
(2) 支持子命令。
(3) 允许替代选项前缀,如+和/。
(4) 处理零个或多个和一个或多个样式参数。
(5) 生成更多信息丰富的使用消息。
(6) 为自定义type和action.

2.2 创建解析器

第一步:实例化一个ArgumentParser对象,创建解析器

import os,sys
import argparse

argpaser = argparse.ArgumentParser(
    description="Realize the function of file recycle bin in Linux environment")

该ArgumentParser对象将保存将命令行解析为 Python 数据类型所需的所有信息。
创建一个新ArgumentParser对象。所有参数都应作为关键字参数传递:

if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        #prog="Anliu",   #项目名字,默认是sys.args[0]
        #usage="",      #用法说明,默认是从参数中自动生成的,例如:Anliu [-h] [--log LOG] int [int ...]
        #description='sum the integers at the command line',  #参数之前项目描述
        #epilog="xxx",  #参数后的文本描述
        #parents="",    #ArgumentParser还应包括其参数的对象列表
        #formatter_class="",   #用于自定义帮助输出的类
        #prefix_chars="+"     #可选参数前缀的字符。
        #fromfile_prefix_chars="",  #该字符集的前缀文件从额外的参数应该读(默认值:None)
        #argument_default="-r",  #为参数的全局默认值(默认值:None)
        #conflict_handler="error", # 解决冲突选项的策略(通常是不必要的)
        #add_help="False",  #添加-h/--help选项解析器(默认值:True)
        #allow_abbrev="False"  #容许长选项缩写。
    )

2.2.1 prog的使用

默认情况下,使用的的sys.args[0]的值:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: myargparse.py [-h] [-r R]

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...

usage的项目名为文件的名字。
当我修改后:

import argparse

parser = argparse.ArgumentParser(
    prog="Anliu"
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [-h] [-r R]

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...

2.2.2 usage的使用

默认情况下,ArgumentParser根据它包含的参数计算使用消息:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [-h] [-r R]

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...

修改后:

import argparse

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...

2.2.3 description

大多数对ArgumentParser构造函数的调用将使用 description=关键字参数。该参数简要描述了程序的作用和工作方式。在帮助消息中,描述显示在命令行用法字符串和各种参数的帮助消息之间:
默认情况下,描述将被换行以适应给定的空间。

import argparse

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    description="This is test of myargparse."
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

This is test of myargparse.

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...

2.2.4 epilog

一些程序喜欢在参数描述之后显示程序的附加描述。可以使用以下epilog= 参数指定此类文本.

import argparse

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    description="This is test of myargparse.",
    epilog="myargparse end."
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

This is test of myargparse.

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...

myargparse end.

2.2.5 parent 的使用

有时,多个解析器共享一组公共参数。无需重复这些参数的定义,而是 可以使用具有所有共享参数并传递给parents=参数 to的单个解析器。

import argparse
parents_parser = argparse.ArgumentParser(add_help=False)
parents_parser.add_argument("-i",help="This test of parents")

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    description="This is test of myargparse.",
    epilog="myargparse end.",
    parents=[parents_parser],
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

This is test of myargparse.

optional arguments:
  -h, --help  show this help message and exit
  -i I        This test of parents
  -r R        test ...

myargparse end.

2.2.6 formatter_class的使用

ArgumentParser对象允许通过指定替代格式类来自定义帮助格式。目前,有三个这样的类:
类argparse.RawDescriptionHelpFormatter
类argparse.RawTextHelpFormatter
类argparse.ArgumentDefaultsHelpFormatter
前两个允许更多地控制文本描述的显示方式,而最后一个自动添加有关参数默认值的信息。
默认情况下,ArgumentParser对象在命令行帮助消息中对描述和结尾文本进行换行:

import argparse
parents_parser = argparse.ArgumentParser(add_help=False)
parents_parser.add_argument("-i",help="This test of parents")

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    description='''
    -------------begin------------
    This is test of myargparse.
    The program used to test argparse.
    please not repeat origro argarse.
    ''',
    epilog='''
    --------------end--------------
    myargparse end.
    Bey.
    ''',
    parents=[parents_parser],
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

-------------begin------------ This is test of myargparse. The program used to
test argparse. please not repeat origro argarse.

optional arguments:
  -h, --help  show this help message and exit
  -i I        This test of parents
  -r R        test ...

--------------end-------------- myargparse end. Bey.

传递RawDescriptionHelpFormatterasformatter_class= 表示描述和结语已经正确格式化,不应换行:

import argparse
parents_parser = argparse.ArgumentParser(add_help=False)
parents_parser.add_argument("-i",help="This test of parents")

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    formatter_class=argparse.RawDescriptionHelpFormatter,
    description='''
    -------------begin------------
    This is test of myargparse.
    The program used to test argparse.
    please not repeat origro argarse.
    ''',
    epilog='''
    --------------end--------------
    myargparse end.
    Bey.
    ''',
    parents=[parents_parser],
)
parser.add_argument("-r", help="test ...")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

    -------------begin------------
    This is test of myargparse.
    The program used to test argparse.
    please not repeat origro argarse.


optional arguments:
  -h, --help  show this help message and exit
  -i I        This test of parents
  -r R        test ...

    --------------end--------------
    myargparse end.
    Bey.

RawTextHelpFormatter为各种帮助文本保留空格,包括参数描述。但是,多个新行被替换为一个。如果您希望保留多个空行,请在换行符之间添加空格。
另一个可用的格式化程序类ArgumentDefaultsHelpFormatter将添加有关每个参数的默认值的信息:

import argparse
parents_parser = argparse.ArgumentParser(add_help=False)
parents_parser.add_argument("-i",help="This test of parents")

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    parents=[parents_parser],
)
parser.add_argument("-r", help="test ...", default="remove")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

optional arguments:
  -h, --help  show this help message and exit
  -i I        This test of parents (default: None)
  -r R        test ... (default: remove)

2.2.7 prefix_chars使用

大多数命令行选项将-用作前缀,这个前缀就可以在这里修改。因为约定俗称,不建议修改。

2.2.8 argument_default使用

指定默认值,当参数没有定义是使用默认。

2.2.9 conflict_handler的使用

ArgumentParser对象不允许具有相同选项字符串的两个操作。默认情况下,ArgumentParser如果尝试使用已在使用的选项字符串创建参数,则对象会引发异常:

import argparse
with open("args.txt","w") as f:
    f.write("-f\nbar")
parents_parser = argparse.ArgumentParser(add_help=False)
parents_parser.add_argument("-i",help="This test of parents")

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    fromfile_prefix_chars="args.txt",
    parents=[parents_parser],
)
parser.add_argument("-r", help="test ...", default="remove")
parser.add_argument("-i",help="This test of parser")
args = parser.parse_args()

执行结果:

PS E:\python 学习\mode_st> python .\myargparse.py -h
Traceback (most recent call last):
    raise ArgumentError(action, message % conflict_string)
argparse.ArgumentError: argument -i: conflicting option string: -i

有时(例如,在使用parents 时)用相同的选项字符串简单地覆盖任何旧参数可能很有用。要获得此行为,'resolve'可以将该值 提供给 的conflict_handler=参数 ArgumentParser:

import argparse
with open("args.txt","w") as f:
    f.write("-f\nbar")
parents_parser = argparse.ArgumentParser(add_help=False)
parents_parser.add_argument("-i",help="This test of parents")

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
    fromfile_prefix_chars="args.txt",
    conflict_handler="resolve",
    parents=[parents_parser],
)
parser.add_argument("-r", help="test ...", default="remove")
parser.add_argument("-i",help="This test of parser")
args = parser.parse_args()

执行结果就正常了。

PS E:\python 学习\mode_st> python .\myargparse.py -h
usage: Anliu [option]

optional arguments:
  -h, --help  show this help message and exit
  -r R        test ...
  -i I        This test of parser

2.2.10 add_help的使用

默认情况下, ArgumentParser 对象添加一个选项,该选项仅显示解析器的帮助消息。有时,禁用此帮助选项的添加可能会很有用。这可以通过False作为add_help=参数传递给ArgumentParser。

2.3 添加参数

ArgumentParser通过调用add_argument()方法来填充有关程序参数的信息。通常,这些调用告诉ArgumentParser如何在命令行上获取字符串并将它们转换为对象。该信息在parse_args()被调用时被存储和使用。
上面的示例中已经大量使用。
接下来我们讨论parse_args()的参数。

  name or flags --Either a name or a list of option strings, e.g. foo or -f, --foo.    
  action --The basic type of action to be taken when this argument is encountered at the command line.
  nargs --The number of command-line arguments that should be consumed.
  const --A constant value required by some action and nargs selections.
  default --The value produced if the argument is absent from the command line.
  type --The type to which the command-line argument should be converted.
  choices --A container of the allowable values for the argument.
  required --Whether or not the command-line option may be omitted (optionals only).
  help --A brief description of what the argument does.
  metavar --A name for the argument in usage messages.
  dest --The name of the attribute to be added to the object returned by parse_args().

参数列表与释义:

参数 选项 释义
action store 存储参数的值,是默认操作。
store_const 指定由canst关键字指定的值。
store_true 转存值true
store_false 转存值false
append 转存为一个列表,这对一次转存多个选项很有用。
append_const 转存为一个列表,并将const执行的关键字参数的值附件到列表。
count 计算关键字出现的次数,对于提高详细级别的计算很有用。
version 调运version关键字参数并打印。
nargs N(一个整数) 选择命令行参数个数,并将其收集到一个列表。
容许默认参数,不指定则为空,不接受default指定,需要const指定。
* 将多个参数收集到一个列表。
+ 和*类似,但是需要至少一个参数。
argparse.REMAINDER 所有剩余的命令行参数都收集到一个列表中。
default 在命令行中可以省略所有可选参数和一些位置参数。
type float,int,argparse.FileType(''),自定义 参数的类型检查和类型转换。
choices 支持in操作符的对象都可以作为choices 值传递,所以dict对象、set对象、自定义容器等都被支持。 选择容器对象。
required True,false 设置必选项
help 打印帮助信息。

下面试一些例举,供大家参考练习。

import argparse
import os, sys
import math

class myaction(argparse.Action):
    def __init__(self, option_strings, dest, nargs=None, **kwargs):
        if nargs is not None:
            raise ValueError("nargs not allowed")
        super(myaction, self).__init__(option_strings, dest, **kwargs)
    def __call__(self, parser, namespace, values, option_string=None):
        print('%r %r %r' % (namespace, values, option_string))
        setattr(namespace, self.dest, values)

def perfect_square(string):
    value = int(string)
    sqrt = math.sqrt(value)
    if sqrt != int(sqrt):
        msg = "%r is not a perfect square" % string
        raise argparse.ArgumentTypeError(msg)
    return value

parser = argparse.ArgumentParser(
    prog="Anliu",
    usage="%(prog)s [option]",
)
parser.add_argument("-n1", action="store")
parser.add_argument("-n2", action="store_const", const=42)
parser.add_argument("-p1", action="store_false")
parser.add_argument("-p2", action="store_true")
parser.add_argument("-p3", action="append")
parser.add_argument("--str", dest="types", action="append_const", const=str)
parser.add_argument("--int", dest="types", action="append_const", const=int)
parser.add_argument("-v", action="count", help="This is a test of anliu")
parser.add_argument("--version", action="version", version='%(prog)s 1.0')
parser.add_argument("-m", action=myaction)
parser.add_argument("-t", nargs=2)
parser.add_argument("-f1", nargs="?", default=2)
parser.add_argument("-f2", nargs="?", const=1, default=2)
parser.add_argument("-a", required=True)
parser.add_argument("-b", nargs="?", type=argparse.FileType("r"), default=sys.stdin)
parser.add_argument("-c", nargs="?", type=argparse.FileType("w"), default=sys.stdout)
parser.add_argument("-d", nargs="*")
parser.add_argument("-e", nargs="+")
parser.add_argument("args", nargs=argparse.REMAINDER)
parser.add_argument("-g", default=10.2, type=int)
parser.add_argument("-i", default=argparse.SUPPRESS)
parser.add_argument("-j", type=perfect_square)
parser.add_argument("-k", choices=["move","delete","get"], help="The option is  %(prog)s, %(default)s")
parser.add_argument("-l", dest="abc")
parser.add_argument('--foo', default=argparse.SUPPRESS)
args = parser.parse_args()
print(args)

2.4 解析参数

parse_args()方法将参数字符串转换为对象并将它们分配为命名空间的属性。返回填充的命名空间。

args     - 要解析的字符串列表。默认值取自 sys.argv.
命名空间  - 获取属性的对象。默认是一个新的空 Namespace对象。

2.5 子命令

许多程序分割它们的功能分成若干子命令。
当程序执行需要不同类型命令行参数的多个不同功能时,以这种方式拆分功能可能是一个特别好的主意。 支持使用方法创建此类子命令 。该方法通常不带参数调用,并返回一个特殊的操作对象。这个对象有一个方法,它接受一个命令名称和任何构造函数参数,并返回一个可以像往常一样修改的对象。

import argparse

# create the top-level parser.
parser = argparse.ArgumentParser(
    prog="Anliu"
) 
parser.add_argument("-foo", action="store_true",help="foo help.")
subparser = parser.add_subparsers(help="sub_command help.")

# create the parse for the "a" command.
parser_a = subparser.add_parser('a', help="a help.")
parser_a.add_argument("bar", type=int, help="bar help.")

# create the parse for the "b" command.
parser_b = subparser.add_parser('b', help="b help.")
parser_b.add_argument("--baz", choices="XYZ", help="baz help.")

#parse some argument lists.
args = parser.parse_args()
print(args)
posted @ 2022-01-01 17:41  大江东流水  阅读(1172)  评论(0编辑  收藏  举报