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)
评论区