python - 使用 python argparse 解析可变数量的命令
问题描述
我正在用 Python 开发一个命令行工具,它的功能被分解为许多子命令,基本上每个子命令都作为参数输入和输出文件。棘手的部分是每个命令需要不同数量的参数(有些不需要输出文件,有些需要多个输入文件等)。
理想情况下,接口将被称为:
./test.py ncinfo inputfile
然后,解析器会意识到该ncinfo
命令需要一个参数(如果这不适合输入命令,它会抱怨),然后它会调用该函数:
ncinfo(inputfile)
做实际的工作。
例如,当命令需要更多选项时
./test.py timmean inputfile outputfile
解析器会意识到这一点,检查是否确实给出了两个参数,然后它调用:
timmean(inputfile, outputfile)
该方案理想地适用于 1 参数命令、2 参数命令等的任意列表。
但是,我正在努力使用 Python 来获得这种行为argparse
。这是我到目前为止所拥有的:
#! /home/navarro/SOFTWARE/anadonda3/bin/python
import argparse
# create the top-level parser
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
# create the parser for the "ncinfo" command
parser_1 = subparsers.add_parser('ncinfo', help='prints out basic netCDF strcuture')
parser_1.add_argument('filein', help='the input file')
# create the parser for the "timmean" command
parser_2 = subparsers.add_parser('timmean', help='calculates temporal mean and stores it in output file')
parser_2.add_argument('filein', help='the input file')
parser_2.add_argument('fileout', help='the output file')
# parse the argument lists
parser.parse_args()
print(parser.filein)
print(parser.fileout)
但这并没有按预期工作。首先,当我调用不带参数的脚本时,我没有收到错误消息告诉我有哪些选项。其次,当我尝试运行要使用的程序时ncinfo
,我得到一个错误
./test.py ncinfo testfile
Traceback (most recent call last):
File "./test.py", line 21, in <module>
print(parser.filein)
AttributeError: 'ArgumentParser' object has no attribute 'filein'
我做错了什么使我无法实现预期的行为?在这种情况下使用是否subparsers
明智?
加分点:有没有办法概括命令的定义,这样我就不需要手动添加每个命令?例如,将所有 1 参数命令分组到一个列表中,然后在循环中定义解析器。这听起来很合理,但我不知道这是否可能。否则,随着工具数量的增加,解析器本身将变得难以维护。
解决方案
import argparse
import sys
SUB_COMMANDS = [
"ncinfo",
"timmean"
]
def ncinfo(args):
print("executing: ncinfo")
print(" inputfile: %s" % args.inputfile)
def timmean(args):
print("executing: timmean")
print(" inputfile: %s" % args.inputfile)
print(" outputfile: %s" % args.outputfile)
def add_parser(subcmd, subparsers):
if subcmd == "ncinfo":
parser = subparsers.add_parser("ncinfo")
parser.add_argument("inputfile", metavar="INPUT")
parser.set_defaults(func=ncinfo)
elif subcmd == "timmean":
parser = subparsers.add_parser("timmean")
parser.add_argument("inputfile", metavar="INPUT")
parser.add_argument("outputfile", metavar="OUTPUT")
parser.set_defaults(func=timmean)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-o', '--common-option', action='store_true')
subparsers = parser.add_subparsers(help="sub-commands")
for cmd in SUB_COMMANDS:
add_parser(cmd, subparsers)
args = parser.parse_args(sys.argv[1:])
if args.common_option:
print("common option is active")
try:
args.func(args)
except AttributeError:
parser.error("too few arguments")
一些使用示例:
$ python test.py --help
usage: test.py [-h] [-o] {ncinfo,timmean} ...
positional arguments:
{ncinfo,timmean} sub-commands
optional arguments:
-h, --help show this help message and exit
-o, --common-option
$ python test.py ncinfo --help
usage: test.py ncinfo [-h] INPUT
positional arguments:
INPUT
optional arguments:
-h, --help show this help message and exit
$ python test.py timmean --help
usage: test.py timmean [-h] INPUT OUTPUT
positional arguments:
INPUT
OUTPUT
optional arguments:
-h, --help show this help message and exit
$ python test.py -o ncinfo foo
common option is active
executing: ncinfo
inputfile: foo
$ python test.py -o timmean foo bar
common option is active
executing: timmean
inputfile: foo
outputfile: bar
推荐阅读
- tensorflow - 多个模型运行的 val 准确度差异很大的原因是什么?
- mysql - 我无法在 ubuntu 上更改 mysql root 密码
- python - 使用 pymupdf-page.searchFor() 选择完全匹配
- python - 通过为多个(但不是全部)级别提供值来选择 pandas MultiIndex DataFrame 中的行
- r - 删除 R 情节子图中的图例重复项
- azure - 如何优化 RU 以替换 Azure cosmos DB 中的文档?
- c++ - Qt 不是模板类型
- json - 如何在 Angular 中剥离这个 JSON?
- javascript - 如何知道列表中 li 的内容?
- hibernate - @OneToMany @MapKeyColumn 关系的可写性映射假定在 @Id 字段上