侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

python - argparse

barwe
2021-12-02 / 0 评论 / 0 点赞 / 877 阅读 / 6,712 字
温馨提示:
本文最后更新于 2022-07-14,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

add_argument() 方法

name_or_flags

命令行中的参数标识符,可以使 位置参数 或者 选项

位置参数不以下划线开头,不用设置简称,例如:

# 命令行参数
# python xxx.py INPUT_VALUE
# 解析器定义
.add_argument('input')
# 对象值
.input #=> INPUT_VALUE

选项以双下划线开头作为对象的键,以单下划线开头作为参数的简称:

# 命令行参数
# python xxx.py --input INPUT_VALUE
# python xxx.py --i INPUT_VALUE
# 解析器定义
.add_argument('--input', '-i')
# 对象值
.input #=> INPUT_VALUE

最终可通过 .input 获取该参数对应的对象,而在命令行中可通过 --input 或者 -i 指定对应参数。

action

将命令行参数的值保存到参数对象中的方式。

'store'

默认操作,存储参数的值到对象。

此时参数应该跟一个值,store 动作会将这个值保存到对象中

# 命令行参数
# python xxx.py -p 3.14159
# 解析器定义
.add_argument('--PI', '-p')
# 对象值
.PI #=> '3.14159'

'store_const'

存储一个常量到对象中,此时参数仅作为标识,不需要跟其他值。

存储的常量通过 const 参数指定,例如:

# 命令行参数
# python xxx.py -p
# 解析器定义
.add_argument('--PI', '-p', action='store_const', const=3.14159)
# 对象值
.PI #=> 3.14159

'store_true' & 'store_false'

store_const 的一个特例,store_true 相当于

# 命令行参数
# python xxx.py --save
# 解析器定义
.add_argument('--save', '-s', action='store_const', const=True, default=False)

其对象默认值为 False,store_false 类似。

'append'

存储一个列表,将每个参数的值追加到列表中。

通过多次使用选项来实现传入多个值,例如

# -f FILE1 -f FILE2 -f FILE3
.add_argument('--file', '-f', action='append')
#=> ['FILE1', 'FILE2', 'FILE3']

'append_const'

将多个参数指定的常数存储到同一个列表中,需要配合 dest 使用:

parser.add_argument('--name', dest='info', action='append_const', const='barwe')
parser.add_argument('--age', dest='info', action='append_const', const=26)
--name
# Namespace(info=['barwe'])
--age
# Namespace(info=[26])
--name --age
# Namespace(info=['barwe', 26])

dest 参数指定了存储对象,这里表示将两个参数的值都添加到列表 info 中。

不使用 dest 时,--name 和 --age 会被分别保存到列表 name 和 age 中。

const 参数默认值为 None。

'count'

计算参数出现的次数:

parser.add_argument('--verbose', '-v', action='count', default=0)
-vv
-v -v
-v --verbose
--verbose --verbose
# Namespace(verbose=2)

需要将 default 显式设为 0,默认为 None。

'help'

help 选项会被自动加入解析器。

'version'

打印版本信息,并在打印后退出程序。需配合 version 参数使用。

parser.add_argument('--version', '-v', action='version', version='1.0.0')
--verison
# 1.0.0

'extend'

存储一个列表,并将每个参数值加入到列表中。

与 append 不同的是,extend 可以用一个参数指定多个值,也可以多次使用参数指定多个值。

需要配合 nargs 参数使用:

parser.add_argument('--names', '-n', action='extend', nargs='+')
# -n barwe chin
#=> Namespace(names=['barwe', 'chin'])

parser.add_argument('--names', '-n', action='extend')
# -n barwe
#=> Namespace(names=['b', 'a', 'r', 'w', 'e'])
# -n barwe chin
#=> error: unrecognized arguments: chin

自定义动作

3.8 以后,通过传递一个 Action 子类或实现相同接口的其他对象来指定任意操作。

3.9 以后,可以扩展 argparse.Action 类并重载 __call__ 方法以及可选的 __init__ 方法和 format_usage 方法来自定义动作。

nargs

消耗参数的数目。不指定时消耗参数的数目由 action 按需要决定。例如 store_const 不消耗参数,store 消耗一个参数。

与 append 和 extend 不同的是,nargs 定义的选项只能调用一次,使用多次时后面的会覆盖前面的。

nargs 支持的值有:

'N'

一个整数,参数中的 N 个参数会被聚集到一个列表中:

parser.add_argument('--names', '-n', nargs=2)
# -n barwe
#=> error: argument --names/-n: expected 2 arguments
# -n barwe chin
#=> Namespace(names=['barwe', 'chin'])
# -n a b -n c d
#=> Namespace(names=['c', 'd'])

特别的,N = 1时会生成一个单元素列表。

'?'

消耗 0 个或者 1 个参数。取决于指定的选项形式:

parser.add_argument('--foo', nargs='?', const='c', default='d')

# 未指定 --foo 时使用 default 值
#=> Namespace(foo='d')

# 指定了 --foo 选项但是未指定值时使用 const 值
# --foo
#=> Namespace(foo='c')

# 指定了 --foo 选项和值
# --foo 'o'
#=> Namespace(foo='o')

default 用于未指定选项时参数的默认值。

const 用于指定了选项但是未指定值时参数的默认值,因为此时会尝试用 store_const 去解析选项。

例如允许可选的输入文件,否则从标准输入读取内容:

parser.add_argument('--input', nargs='?', type=argparse.FileType('r'), default=sys.stdin)

nargs='?' 必须为选项指定0个或者1个参数,否则报错。

'*'

选项 后的所有参数聚集到一个列表中,允许选项不带参数。

'+'

'*' 类似,但是选项后至少需要有一个参数,否则报错。

const

const 用来保存命令行中未指定但是该 action 又需要的常量。常见的用法有:

  • action'store_const' 或者 'append_const' 时将 const 指定的值保存到列表
  • nargs'?' 时,如果选项后面没有跟参数,则保存 const 指定的值到对象

'store_const''append_const' 动作,必须给出 const 的值,其他动作默认为 None

default

default 指定了选项在命令行参数中未出现时应当使用的值。

default=argparse.SUPPRESS 设置在命令行中未出现该选项时,不添加字段到 Namespace 中。因为 default 有默认值,未指定选项时会添加 KEY => None 到 Namesapce 中。

type

默认情况下,解析器会将命令行参数当作简单字符串读入,type 关键字允许执行任何必要的类型检查和类型转换。

任何可接受单个字符串作为第一个参数的可调用对象都能作为 type 参数的值,常见的有:

  • 普通的内置类型,例如 int, float, ord, open, path.Path 以及 argparse.FileType('w')
  • 自定义的函数,以字符串类型作为第一个参数,返回的值作为参数实际存储的值;类型检查引发的错误应为 argparse.ArgumentTypeError, TypeError 或者 ValueError 中的一种,其他异常不会被解析器处理

choices

选项的参数值必须在指定的值列表中,该判断发生在 type 参数的类型检查和转换之后。

parser.add_argument('move', choices=['rock', 'paper', 'scissors'])

值列表是一个容器对象,如 list, set, range

required

将选项标记为必须参数,==尽量不用==。必须参数应使用 位置参数 而不是选项。

parser.add_argument('--foo', required=True)

help

值是一个包含参数简短描述的字符串。

参数中可以包含 格式描述符

  • 程序名称:%{prog}s,在初始化解析器时通过 prog 参数指定
  • 传给 add_argument() 的大部分关键字参数,例如 %{type}s, %{default}s
parser = argparse.ArgumentParser(prog='frobble')
parser.add_argument('bar', nargs='?', type=int, default=42, help='the bar to %(prog)s (default: %(default)s)')

参数字符串支持 % 格式化,因此打印 % 字符需要使用 % 转义,即 %%

通过设置 help=argparse.SUPPRESS 来隐藏帮助文档中未显示设置 help 信息的参数。

metavar

帮助文档中描述参数值的一种符号,例如 --foo FOO 表示 --foo 选项需要一个值,FOO 相当于一种占位符。

位置参数使用 dest 值的小写形式作为占位符,选项使用其 dest 的值的大写形式作为占位符:

parser.add_argument('bar')
parser.add_argument('--foo')
python xxx.py -h
usage:  [-h] [--foo FOO] bar

positional arguments:
 bar

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

metavar 参数用来指定这个占位符的值,只是为了显示,它不改变参数对象的属性名称,属性名称仍是由 dest 确定。

parser.add_argument('--foo', metavar='YYY')
# 帮助文档中将显示 --foo YYY

当参数有 nargs 时,可以给 metavar 传入一个 tuple 来为每一个值显示一个占位符。

parser.add_argument('--foo', nargs=2, metavar=('FOO1', 'FOO2'))
# --foo FOO1 FOO2

dest

解析器会将参数的名称保存为参数对象(调用 parser.parse_args() 返回)的一个属性,通过 .ATTR 形式访问参数的属性来获取参数的值。

add_argument() 方法通过 dest 关键字来为每个参数指定属性名称,默认情况下:

  • 位置参数的 dest 值就是 add_argument() 方法的第一个参数值
  • 选项的 dest 值通过 add_argument() 的 flags 进行转换:
    • 有长选项(以 -- 开头)时,例如 --input-file 被转换为 input_file
    • 没有长选项时对短选项(以 - 开头)进行转换
    • 短选项也没有,怎么可能呢?

通过显示指定 dest 关键字为参数使用自定义的属性名:

parser.add_argument('--input-file', '-i', dest='input_fasta')
args = parser.parse_args()
args.input_fasta #=> right
args.input_file #=> wrong

Action

https://docs.python.org/zh-cn/3/library/argparse.html#action-classes

parse_args() 方法

https://docs.python.org/zh-cn/3/library/argparse.html#the-parse-args-method

Namespace

一个结构非常简单的类,每个参数作为对象的属性进行访问。

可以通过 vars(namespace) 方法转换为 Python 标准字典来访问。

https://docs.python.org/zh-cn/3/library/argparse.html#the-namespace-object

解析器的 add_subparsers() 方法

将程序的功能拆分成一系列的子命令,例如 git merge, git add

## 初始化一个主解析器
parser = argparse.ArgumentParser(prog='git')

## 为主解析器添加一个选项
parser.add_argument('--version', '-v', action='version', version='1.0.0', help='')

## 获取为主解析器的添加子解析器的动作对象
subparsers = parser.add_subparsers(help='')

## 初始化一个子解析器
parser_1 = subparsers.add_parser('add', help='')

## 为子解析器添加参数和选项
parser_1.add_argument('files', nargs='+', help='')

## 初始化一个新的子解析器
parser_2 = subparsers.add_parser('commit', help='')

## 为子解析器添加参数和选项
parser_1.add_argument('--message', '-m', help='')

## 解析参数返回参数对象
args: argparse.Namespace = parser.parse_args()
    
## 可转换为内置字典
args = vars(args)

https://docs.python.org/zh-cn/3/library/argparse.html#argparse.ArgumentParser.add_subparsers

帮助文档的换行问题

argparse 默认将帮助文本中的所有换行符和连续空格替换成单个空格。

解决办法:实现自己的文本格式化类

from argparse import HelpFormatter

class SmartFormatter(HelpFormatter):
    def _split_lines(self, text: str, width: int) -> list[str]:
        return [s.strip(' \n') for s in text.strip(' \n').split('\n')]

对于帮助文本,首先去除其首尾的换行符和空格,然后去除其每一行首尾的换行符和空格。这样做是为了兼容多行字符串(即通过三个单引号或者三个双引号引起来的字符串)的显示格式。

然后在获取解析器或者子解析器时指定自定义的文本格式化类:

parser = ArgumentParser(formatter_class=SmartFormatter)

子解析器需要单独指定才能生效:

parser = ArgumentParser()
subparsers = parser.add_subparsers()
p: ArgumentParser = subparsers.add_parser('bio', formatter_class=SmartFormatter)
0

评论区