Argparse:如何接受任意数量的可选参数(以“-”或“--”开头)
Argparse: How to accept any number of optional arguments (starting with `-` or `--`)
我正在尝试创建一个命令行工具(我们称之为 'X')来包装另一个工具(我们称之为 'Y')。
有些情况我是专门处理的,自己也加了一些选项,但是不想处理的我想重定向到工具Y
到目前为止,我设法重定向了不带破折号的参数,例如 X Y option1 option2 option3
将只调用 Y option1 option2 option3
。我通过添加一个子解析器 Y
和一个参数 any
来做到这一点
这是代码 (x.py):
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="parser_name")
y_subparser = subparsers.add_parser('y')
y_options = y_subparser.add_argument('any', nargs='*')
然后在我的处理程序代码中,我这样做:
args = main_parser.parse_args()
if args.parser_name == 'y':
command_string = ' '.join(['y'] + sys.argv[2:])
os.system(command_string)
当我调用 python x.py y asdf zxcv qwer
时它起作用了。
当我调用 python x.py y asdf zxcv qwer -option
时出现错误 x.py: error: unrecognized arguments: -option
我意识到如果 argparse 变得太复杂,我总是可以退回到使用 sys.argv
,但如果你知道这是可行的,请分享。
我也一直在查看 argparse 代码,它有点密集,似乎 ArgumentParser._parse_known_args
完成了所有事情(300 行)。但在我深入之前,我想也许有人知道如何做到这一点 - 如果不知道,我会 post 如果其他人有同样的问题,我会在这里发现我的发现。
从 argparse 的文档中,您可以使用 argparse.REMAINDER
:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')
即使在子命令参数中使用虚线也能正常工作
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ --foobar'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ', '--foobar'], command='cmd', foo='B')
我找到了这个解决方法:
而不是简单地使用 main_parser.parse_args()
我这样做
def remove_dashes_from_args(args):
return [arg.replace('-','#$%#$') for arg in args]
main_parser.parse_args(replace_dashes_from_args(sys.argv[1:]))
然后在调用 Y
命令时我不需要更改任何内容,因为我已经在使用 sys.argv:
if arg.parser_name == 'y':
os.system(' '.join(['y'] + sys.argv[2:]))
我正在尝试创建一个命令行工具(我们称之为 'X')来包装另一个工具(我们称之为 'Y')。
有些情况我是专门处理的,自己也加了一些选项,但是不想处理的我想重定向到工具Y
到目前为止,我设法重定向了不带破折号的参数,例如 X Y option1 option2 option3
将只调用 Y option1 option2 option3
。我通过添加一个子解析器 Y
和一个参数 any
来做到这一点
这是代码 (x.py):
main_parser = argparse.ArgumentParser()
subparsers = main_parser.add_subparsers(dest="parser_name")
y_subparser = subparsers.add_parser('y')
y_options = y_subparser.add_argument('any', nargs='*')
然后在我的处理程序代码中,我这样做:
args = main_parser.parse_args()
if args.parser_name == 'y':
command_string = ' '.join(['y'] + sys.argv[2:])
os.system(command_string)
当我调用 python x.py y asdf zxcv qwer
时它起作用了。
当我调用 python x.py y asdf zxcv qwer -option
时出现错误 x.py: error: unrecognized arguments: -option
我意识到如果 argparse 变得太复杂,我总是可以退回到使用 sys.argv
,但如果你知道这是可行的,请分享。
我也一直在查看 argparse 代码,它有点密集,似乎 ArgumentParser._parse_known_args
完成了所有事情(300 行)。但在我深入之前,我想也许有人知道如何做到这一点 - 如果不知道,我会 post 如果其他人有同样的问题,我会在这里发现我的发现。
从 argparse 的文档中,您可以使用 argparse.REMAINDER
:
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ'], command='cmd', foo='B')
即使在子命令参数中使用虚线也能正常工作
>>> parser = argparse.ArgumentParser(prog='PROG')
>>> parser.add_argument('--foo')
>>> parser.add_argument('command')
>>> parser.add_argument('args', nargs=argparse.REMAINDER)
>>> print(parser.parse_args('--foo B cmd --arg1 XX ZZ --foobar'.split()))
Namespace(args=['--arg1', 'XX', 'ZZ', '--foobar'], command='cmd', foo='B')
我找到了这个解决方法:
而不是简单地使用 main_parser.parse_args()
我这样做
def remove_dashes_from_args(args):
return [arg.replace('-','#$%#$') for arg in args]
main_parser.parse_args(replace_dashes_from_args(sys.argv[1:]))
然后在调用 Y
命令时我不需要更改任何内容,因为我已经在使用 sys.argv:
if arg.parser_name == 'y':
os.system(' '.join(['y'] + sys.argv[2:]))