Have argparse collect, but not respond to, flags

时光毁灭记忆、已成空白 提交于 2019-12-13 01:29:48

问题


I have a script which takes in some arguments, uses some of those argument to choose a script to run, and passes the rest of the arguments to that script. So it looks something like this:

parser = ArgumentParser()
parser.add_argument('script', choices['a', 'b'])
parser.add_argument('rest_args', nargs='*')
args = parser.parse_args()
if args.script == 'a':
    subprocess.call('python a.py %s' % ' '.join(args.rest_args))
else:
    subprocess.call('python b.py %s' % ' '.join(args.rest_args))

This works fine, unless I want to pass in arguments that start with -. For example, if I called python my_script.py a --foo, I'd get an error unrecognized arguments, when really I want to just have it run python a.py --foo (i.e. just pass the --foo along to the subprocess).

Is there a way to get around this with argparse?


回答1:


Perhaps you are looking for parse_known_args. It will parse all the options it recognizes, and returns all the unrecognized arguments in unknown:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('script', choices=['a', 'b'])

args, unknown = parser.parse_known_args(['a', '--foo'])

print(args)
# Namespace(script='a')
print(unknown)
# ['--foo']



回答2:


I discovered the function parse_known_args, which provides a solution to this, albeit perhaps not ideal.

parser = ArgumentParser()
parser.add_argument('script', choices['a', 'b'])
args, rest_args = parser.parse_known_args()
if args.script == 'a':
    subprocess.call('python a.py %s' % ' '.join(rest_args))
else:
    subprocess.call('python b.py %s' % ' '.join(rest_args))

What this does is use parse_known_args to parse what's known, and collect the rest in a list. Then those remaining arguments can be passed to the subprocess as desired.




回答3:


The '*' works if you include '--' in the argument list:

1502:~/mypy$ python2.7 stack26264831.py a -- --foo bar
Namespace(rest_args=['--foo', 'bar'], script='a')

An alternative is to use REMAINDER ('...') instead of '*':

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('script', choices=['a', 'b'])
parser.add_argument('rest_args', nargs=argparse.REMAINDER)
args = parser.parse_args()
print args

1500:~/mypy$ python2.7 stack26264831.py a --foo bar
Namespace(rest_args=['--foo', 'bar'], script='a')

Both the '--' and REMAINDER mean: 'treat what follows as positional arguments'.

parse_known_args also works, though its logic is different - 'just return a list of the strings you didn't recognize'. parse_args calls parse_known_args and raises an error is the rest value is not empty.


But don't use REMAINDER as the first positional argument: Using argparse.REMAINDER at beginning of parser / sub parser



来源:https://stackoverflow.com/questions/26264831/have-argparse-collect-but-not-respond-to-flags

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!