使用python的argparse,如何使子命令成为必需的参数?我想这样做是因为如果没有指定子命令,我希望argparse出错.我改写错误方法来打印帮助.我有3个深度嵌套子命令,所以这不是简单地在顶层处理零参数的问题.
在下面的示例中,如果这样调用,我得到:
$./simple.py
$
Run Code Online (Sandbox Code Playgroud)
我想要它做的是让argparse抱怨没有指定所需的子命令:
import argparse
class MyArgumentParser(argparse.ArgumentParser):
def error(self, message):
self.print_help(sys.stderr)
self.exit(0, '%s: error: %s\n' % (self.prog, message))
def main():
parser = MyArgumentParser(description='Simple example')
subs = parser.add_subparsers()
sub_one = subs.add_parser('one', help='does something')
sub_two = subs.add_parser('two', help='does something else')
parser.parse_args()
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud) 我正在使用argparse构建一个带有子命令的命令:
mycommand [GLOBAL FLAGS]子命令[FLAGS]
我希望全局标志能够工作,无论它们是在子命令之前还是之后.有没有一个干净的方法来做这个不涉及重复代码?
例如:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest='subparser_name')
parser.add_argument('--disable') # This flag...
sp = subparsers.add_parser('compile')
sp.add_argument('zones', nargs='*')
sp.add_argument('--disable') # Is repeated...
sp = subparsers.add_parser('launch')
sp.add_argument('zones', nargs='*')
sp.add_argument('--disable') # over and over...
Run Code Online (Sandbox Code Playgroud)
我想为许多旗帜做这件事,所以一遍又一遍地重复自己似乎...... unpythonic.
argparse在处理接收全局选项的子命令时失败:
import argparse
p = argparse.ArgumentParser()
p.add_argument('--arg', action='store_true')
s = p.add_subparsers()
s.add_parser('test')
Run Code Online (Sandbox Code Playgroud)
会有p.parse_args('--arg test'.split())工作,
但失败了p.parse_args('test --arg'.split()).
有谁知道python参数解析器正确处理子命令的全局选项?
使用argparse时,一些子命令需要相同的选项,我用它parents来避免在每个子命令中重复定义它们.
脚本文件名: testarg.py
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-H', '--host', default='192.168.122.1')
parser.add_argument('-P', '--port', default='12345')
subparsers = parser.add_subparsers()
# subcommand a
parser_a = subparsers.add_parser('a', parents=[parser])
parser_a.add_argument('-D', '--daemon', action='store_true')
parser_a.add_argument('-L', '--log', default='/tmp/test.log')
# subcommand b
parser_b = subparsers.add_parser('b', parents=[parser])
parser_b.add_argument('-D', '--daemon', action='store_true')
# subcommand c
parser_c = subparsers.add_parser('c', parents=[parser])
args = parser.parse_args()
print args
Run Code Online (Sandbox Code Playgroud)
但是当我运行命令时:
>>>./testarg.py a
usage: testarg.py a [-h] [-H HOST] [-P PORT] [-D] [-L LOG] {a,b,c} ...
testarg.py a: error: too few arguments
Run Code Online (Sandbox Code Playgroud)
期待输出:
>>>./testarg.py a
Namespace(daemon=False, …Run Code Online (Sandbox Code Playgroud) 我正在为我的 Python 应用程序添加 CLI。CLI 应允许一次运行多个命令。命令应该有公共选项和个人选项。
例子:
$ python mycliapp.py --common-option1 value1 --common-option2 value2 cmd1 --cmd1-option cmd2 --cmd2-option somevalue cmd3
Run Code Online (Sandbox Code Playgroud)
该示例有两个所有命令都使用的公共选项,并且每个命令可以有或没有仅该命令使用的选项。
我考虑过Python Click。它具有丰富的功能,但它不允许(至少我没有发现)在没有一些主命令的情况下使用常用选项。
使用 Click 时,上面的示例将如下所示:
$ python mycliapp.py maincmd --common-option1 value1 --common-option2 value2 cmd1 --cmd1-option cmd2 --cmd2-option somevalue cmd3
Run Code Online (Sandbox Code Playgroud)
另外,还考虑了 Python Argparse。看起来它可以满足我的需要,并且我已经成功编写了一个代码,该代码可以使用常见选项和单个命令,但无法使用多个命令。此页面Python argparse - Add argument to multiple subparsers有很好的示例,但似乎 command2 应该是 command1 的子命令。它有点不同,因为我需要命令可以按任何顺序执行。
我制作了一个执行很多操作的 Python 脚本,所以它有很多选项,所以我将它划分为也使用父解析器进行公共选项分组的子解析器。
我想要一个帮助选项来显示所有命令的帮助及其选项,是否可以不覆盖 format_help 方法?
我看到了一个类似的问题,但分组对我来说并不重要,我只想要那里的选项。
例如:
general_group = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,add_help=False)
general_group.add_argument('--threads', action='store_true', default=False)
second_group = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter,add_help=False)
second_group.add_argument('--sleep', action='store', default=60, type=int)
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
subparsers=parser.add_subparsers(dest='action')
subparsers.add_parser('Restart',parents=[general_group,second_group])
subparsers.add_parser('Start',parents=[general_group])
args = parser.parse_args()
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我希望如果有人运行 ./script.py -h 他们会在帮助中看到线程选项。
我将 argparse 与几个子解析器一起使用。我希望我的程序在 args 中的任何地方都采用详细程度的选项,包括子解析器。
from argparse import ArgumentParser
p = ArgumentParser()
p.add_argument('--verbose', '-v', action='count')
sub = p.add_subparsers()
a = sub.add_parser('a')
print(p.parse_args())
Run Code Online (Sandbox Code Playgroud)
默认情况下,如果用于子解析器,主解析器的选项将抛出错误:
$ python tmp.py -v a
Namespace(verbose=1)
$ python tmp.py a -v
usage: tmp.py [-h] [--verbose] {a} ...
tmp.py: error: unrecognized arguments: -v
Run Code Online (Sandbox Code Playgroud)
我从这个答案中查看了父解析器。
from argparse import ArgumentParser
parent = ArgumentParser(add_help=False)
parent.add_argument('--verbose', '-v', action='count')
main = ArgumentParser(parents=[parent])
sub = main.add_subparsers()
a = sub.add_parser('a', parents=[parent])
print(main.parse_args())
Run Code Online (Sandbox Code Playgroud)
但是由于某种原因,没有一个共享标志在主解析器上工作。
$ python tmp2.py a -vvv
Namespace(verbose=3)
$ python tmp2.py -vvv …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用argparse模块向多个subparser添加所需的输入文件名和可选的输出文件名.
这是我的尝试:
# test_argparse.py
import argparse
def setup_parser():
parser = argparse.ArgumentParser(prog='test_argparse.py',
formatter_class=argparse.RawDescriptionHelpFormatter,
description='Testing the argparse module.')
parser.add_argument('--version', action='version', version='%(prog)s 1.0')
subparsers = parser.add_subparsers()
parser_actionA = subparsers.add_parser('actionA')
parser_actionB = subparsers.add_parser('actionB')
parser_actionC = subparsers.add_parser('actionC')
parser.add_argument('infile', nargs=1, help='input mesh file name')
parser.add_argument('outfile', nargs='?', help='output mesh file name')
return parser
if __name__ == '__main__':
parser = setup_parser()
args = parser.parse_args()
print args
Run Code Online (Sandbox Code Playgroud)
如果我执行这个:
python test_argparse.py actionA infile outfile
Run Code Online (Sandbox Code Playgroud)
它不起作用,我得到的是:
usage: test_argparse.py [-h] [--version]
{actionA,actionB,actionC} ... infile [outfile]
test_argparse.py: error: unrecognized arguments: infile
Run Code Online (Sandbox Code Playgroud)