One optional argument which does not require positional arguments

本小妞迷上赌 提交于 2019-12-04 13:43:57

问题


I have a question regarding python's argparse: Is it possible to have a optional argument, which does not require positional arguments?

Example:

parser.add_argument('lat', help="latitude")
parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")
parser.add_argument('--list-methods', help="list available methods", action="store_true")

The normal command line would be test.py 47.249 -33.282 or test.py 47.249 -33.282 --method sub. But as soon as I call the script with test.py --list-methods to list all available methods, I get error: to few arguments. How can I use argparse to have this optional argument (--list-methods) without having positional arguments (lat, lon)?


回答1:


  • set a default value and nargs='?' for your positional arguments
  • check manually in your code that both latitude and longitude have been set when you're not in list-methods mode

    parser = argparse.ArgumentParser()
    
    parser.add_argument('lat', help="latitude",default=None, nargs='?')
    parser.add_argument('lon', help="longitude",default=None, nargs='?')
    parser.add_argument('--method', help="calculation method (default: add)", default="add")
    parser.add_argument('--list-methods', help="list available methods", action="store_true")
    
    args = vars(parser.parse_args())
    
    if not args['list_methods'] and (args['lat'] == None or args['lon'] == None):
        print '%s: error: too few arguments' % sys.argv[0]
        exit(0)
    
    if args['list_methods']:
        print 'list methods here'
    else :
        print 'normal script execution'
    

which gives :

$ test.py --list-methods
list methods here

$ test.py 4
test.py: error: too few arguments

test.py 4 5
normal script execution




回答2:


As of Python 3.3, parse_args checks its set of seen_actions against the set of actions that are required, and issues a the following arguments are required... error as needed. Previously it checked its list of remaining positionals and raised the too few arguments error message.

So for newer versions, this snippet should do what you want:

parser = argparse.ArgumentParser()
lat=parser.add_argument('lat', help="latitude")
lon=parser.add_argument('lon', help="longitude")
parser.add_argument('--method', help="calculation method (default: add)", default="add")

class MyAction(argparse._StoreTrueAction):
    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, self.const)
        lat.required = False
        lon.required = False

parser.add_argument('--list-methods', help="list available methods", action=MyAction)

Normally lat and lon are required positionals, but if the --list... action is taken, those actions are no longer required, and no error message is raised if they are missing.


Another way to customize argparse is to use several parsers. In this case you could use one parser to check for the --list-methods option, and based on what it gets, call another that looks for the positionals.

parser1 = argparse.ArgumentParser(add_help=False)
parser1.add_argument('--list-methods', help="list available methods", action='store_true')

parser2 = argparse.ArgumentParser()
parser2.add_argument('lat', help="latitude")
parser2.add_argument('lon', help="longitude")
parser2.add_argument('--method', help="calculation method (default: add)", default="add")
parser2.add_argument('--list-methods', help="list available methods", action='store_true')
def foo(argv):
    args,rest = parser1.parse_known_args(argv)
    if not args.list_methods:
        args = parser2.parse_args(argv)
    return args

parser2 responds to the help command. parse_known_args parses what it can, and returns the rest in a list. parser2 could also have been write to take rest, args as arguments.




回答3:


You get error: to few arguments because lat and lon arguments are required.

In [10]: parser.parse_args('--list-methods'.split())
ipython: error: too few arguments

but

In [11]: parser.parse_args('--list-methods 10 20'.split())
Out[11]: Namespace(lat='10', list_methods=True, lon='20', method='add')

You should make lat and lon arguments optional.



来源:https://stackoverflow.com/questions/6880169/one-optional-argument-which-does-not-require-positional-arguments

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