从外部模块添加argparse参数
我正在尝试写一个可以被第三方扩展的Python程序。这个程序会从命令行运行,并接受用户提供的各种参数。
为了让第三方能够创建自己的模块,我创建了一个简化的基础类:
class MyBaseClass(object):
def __init__(self):
self.description = ''
self.command = ''
def get_args(self):
# code that I can't figure out to specify argparse arguments here
# args = []
# arg.append(.....)
return args
他们通过get_args()提供的任何参数都会被添加到特定模块的子解析器中。我希望他们能够指定任何类型的参数。
我不太确定如何最好地声明这些参数,然后把它们从子类模块获取到我的主程序中。我成功找到了所有MyBaseClass的子类,并循环遍历它们来创建子解析器,但我找不到一个干净的方法来将各个参数添加到子解析器中。
这是主程序当前的代码:
for module in find_modules():
m = module()
subparser_dict[module.__name__] = subparsers.add_parser(m.command, help=m.help)
for arg in m.get_args():
subparser_dict[module.__name__].add_argument(...)
我该如何通过get_args()或类似的方法在外部模块中最好地指定参数,然后将它们添加到子解析器中?我之前的一次失败尝试看起来像这样,但它不工作,因为它试图将每一个可能的选项都传递给add_argument(),无论它是否有值或者是None:
subparser_dict[module.__name__].add_argument(arg['long-arg'],
action=arg['action'],
nargs=arg['nargs'],
const=arg['const'],
default=arg['default'],
type=arg['type'],
choices=arg['choices'],
required=arg['required'],
help=arg['help'],
metavar=arg['metavar'],
dest=arg['dest'],
)
2 个回答
我建议你在你的 get_args
方法中返回一个 ArgumentParser
的实例。这样,你就可以创建一个新的 ArgumentParser
,并通过 parents
参数把其他所有的参数解析器连接起来。具体可以参考这个链接:https://docs.python.org/3/library/argparse.html#parents。
在不深入了解你的模块结构的情况下,我觉得你想要的是能够把参数以对象的形式提供给一个 add_argument
的调用,这样你就可以导入它们。
比如,你可以提供一个位置参数的列表和一个关键字参数的字典:
args=['-f','--foo']
kwargs={'type':int, 'nargs':'*', 'help':'this is a help line'}
parser=argparse.ArgumentParser()
parser.add_argument(*args, **kwargs)
parser.print_help()
这样就会产生
usage: ipython [-h] [-f [FOO [FOO ...]]]
optional arguments:
-h, --help show this help message and exit
-f [FOO [FOO ...]], --foo [FOO [FOO ...]]
this is a help line
在 argparse.py
文件中,add_argument
方法(这是 ArgumentParser
的一个父类的方法)大致是这个样子的:
def add_argument(self, *args, **kwargs):
这个方法的代码会处理这些参数,把 args
加到 kwargs
中,添加默认值,最后把 kwargs
传递给合适的 Action
类,并返回新的动作。(它还会把这个动作“注册”到解析器或子解析器中)。实际上,Action
子类的 __init__
方法会列出参数及其默认值。