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