问题
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