通常,要在
argparse
中添加子解析器,您必须执行以下操作:
parser = ArgumentParser()
subparsers = parser.add_subparser()
subparser = subparsers.add_parser()
我遇到的问题是我正在尝试添加另一个命令行脚本及其自己的解析器,作为主脚本的子命令。有没有简单的方法可以做到这一点?
编辑:为了澄清,我有一个文件
script.py
,看起来像这样:
def initparser():
parser = argparse.ArgumentParser()
parser.add_argument('--foo')
parser.add_argument('--bar')
return parser
def func(args):
#args is a Namespace, this function does stuff with it
if __name__ == '__main__':
initparser().parse_args()
所以我可以这样运行:
python script.py --foo --bar
我正在尝试编写一个模块
app.py
,这是一个带有多个子命令的命令行界面,因此我可以运行类似的命令:
python app.py script --foo --bar
我希望能够直接使用从 initparser() 创建的解析器作为子解析器,而不是将所有
initparser()
逻辑复制并粘贴到 app.py
。这可能吗?
您可以使用
parents
参数
p = argparse.ArgumentParser()
s = p.add_subparsers()
ss = s.add_parser('script', parents=[initparser()], add_help=False)
p.parse_args('script --foo sst'.split())
ss
是一个解析器,共享为 initparser
定义的所有参数。 add_help=False
或 ss
都需要 initparser
,因此 -h
不会被定义两次。
您可能想看一下 shlex 模块,因为在我看来,您正在尝试破解
ArgumentParser
来做一些实际上并不打算做的事情。
话虽如此,如果没有您要尝试解析的确切内容的示例,就很难找到一个好的答案。
我认为你的问题可以通过 argparse 的声明性包装来解决。我写的那个叫Argh。它有助于将命令的定义(以及所有与参数相关的内容)与组装(包括子解析器)和分派分开。
这是一个很老的问题,但我想抛出另一种选择。这就是从控制反转的角度来思考。我的意思是根
ArgumentParser
将管理子解析器的创建:
# root_argparser.py
from argparse import ArgumentParser, Namespace
__ARG_PARSER = ArgumentParser('My Script')
__SUBPARSERS = __ARG_PARSER.add_subparsers(dest='subcommand')
__SUBPARSERS.required = True
def get_subparser(name: str, **kwargs) -> ArgumentParser:
return __SUBPARSERS.add_parser(name, **kwargs)
def parse_args(**kwargs) -> Namespace:
return __ARG_PARSER.parse_args(**kwargs)
# my_script.py
from argparse import ArgumentParser
from root_argparse import get_subparser
__ARG_PARSER = get_subparser('script')
__ARG_PARSER.add_argument('--foo')
__ARG_PARSER.add_argument('--bar')
def do_stuff(...):
...
# main.py
from root_argparse import parse_args
import my_script
if __name__ == '__main__':
args = parse_args()
# do stuff with args
从我所做的一些快速测试来看,似乎工作正常。