Reputation: 21238
I want to use python-argparse with arguments and positional arguments. Say I have my script on a commandline (which is just a simple&stupid example), this is my code so far:
#!/usr/bin/env python
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', action='store_true')
subparsers = parser.add_subparsers(help='command', dest='command')
cmd1_parser = subparsers.add_parser('command1')
cmd1_parser.add_argument('--verbose', action='store_true')
args = parser.parse_args()
print args
Now I call this script like this:
~ $ myscript --verbose command1 --verbose
Namespace(command='command1', verbose=True)
~ $ myscript command1 --verbose
Namespace(command='command1', verbose=True)
~ $ myscript --verbose command1
Namespace(command='command1', verbose=True)
Now as you can see I always get the same Namespace-object, and cannot distinguish if the verbose command is a regular parameter or a subparser parameter. But I need that to handle these parameters separately. What would be an easy way (with minimum code efforts) to do that?
EDIT:
I filed an issue inside the Python stdlib issue tracker: http://bugs.python.org/issue15327
Upvotes: 4
Views: 2234
Reputation: 309891
Here's a little something I hacked together. I would almost guarantee it isn't bug free, but it worked on this simple test.
import argparse
class _Action(object):
def __init__(self,master):
self.master=master
def add_parser(self,name,**kwargs):
self.master.subparsers[name]=subParserEnabler()
return self.master.subparsers[name]
class subParserEnabler(argparse.ArgumentParser):
def __init__(self,*args,**kwargs):
self.subparsers={}
argparse.ArgumentParser.__init__(self,*args,**kwargs)
def add_subparsers(self,**kwargs):
return _Action(self)
def parse_args(self,args,**kwargs):
args=list(args)
for k in self.subparsers.keys():
if k in args:
break
try:
i=args.index(k)
output=argparse.ArgumentParser.parse_args(self,args[:i],**kwargs)
o1=argparse.Namespace()
setattr(output,k,o1)
self.subparsers[k].parse_args(args[i+1:],namespace=o1)
except:
output=argparse.ArgumentParser.parse_args(self,args,**kwargs)
return output
parser = subParserEnabler()
parser.add_argument('--verbose', action='store_true')
subparsers = parser.add_subparsers(help='command',dest='command')
cmd1_parser = subparsers.add_parser('command1')
cmd1_parser.add_argument('--verbose', action='store_false')
args = parser.parse_args("--verbose command1 --verbose".split())
print args
It's still missing aliases and the help formatting is probably wrong...but at least it provides the output I wanted. Ultimately, John Gaines Jr's answer is probably a lot simpler than mine though.
Upvotes: 4
Reputation: 11534
Change your subparser's add_argument call to this:
cmd1_parser.add_argument('--verbose', action='store_true', dest='cmd1_verbose')
This will result in your first example returning:
~ $ myscript --verbose command1 --verbose
Namespace(cmd1_verbose=True, command='command1', verbose=True)
Upvotes: 5