Python argparse without value

Argparse — Custom Action With No Argument?

I know normally having the action be something like ‘store_true’ would prevent the requirement of an argument, but is there a way to use a custom action and still not require an argument to be passed? So what I want is:

4 Answers 4

Try adding nargs=0 to your start.add_argument :

start.add_argument('-s', '--start', action=StartAction, nargs=0) 

ValueError: nargs for store actions must be > 0; if you have nothing to store, actions such as store true or store const may be more appropriate

I don’t agree with @Lucina comment. You may want to call a custom action to have a seamless mapping between parsing arguments and complex actions. I prefere to have Action objects that behave as the parameters of the CLI so I have polymorphism between the CLI itnerface and the object that handles it.

As mgilson suggested nargs=0 does the trick. Since it’s intrinsic to your action, I’d put it inside the action:

class StartAction(argparse.Action): def __init__(self, nargs=0, **kw): super().__init__(nargs=nargs, **kw) def __call__(self, parser, namespace, values, option_string=None): print "Hello" start.add_argument('-s', '--start', action=StartAction) 

And you have your desired behaviour without the redundancy of having to add nargs=0 to every add_argument() call. Neat if you have multiple arguments working in the same way.

However users could still override the default of nargs=0 which is silly for your use case as demonstrated in the question. So I’d enforce it:

class StartAction(argparse.Action): def __init__(self, nargs=0, **kw): if nargs != 0: raise ValueError('nargs for StartAction must be 0; it is ' 'just a flag.') super().__init__(nargs=nargs, **kw) def __call__(self, parser, namespace, values, option_string=None): print "Hello" 

The former (without the enforcing check) is also exactly what action=»store_const» does: github.com/python/cpython/blob/…

For anyone who finds this in 2020: If you attempt to pass nargs=0 in the latest argparse package for python3, it will error with:

ValueError: nargs for store actions must be != 0; if you have nothing to store, actions such as store true or store const may be more appropriate 

The solution you’re probably looking for is to pass action=»store_const» and const=True

parser = argparse.ArgumentParser parser.add_argument('-s', '--start', help='Start script or whatever', action="store_const", const=True) 

This will set the value for parser.start equal to «True» when the -s parameter is passed to main/the rest of the script.

Читайте также:  Css stylesheets in html

I wrote this example after consulting the above and trying out different methods. Here is a class which implements the «Uncount» acount, which is the opposite of the ‘count’ action.

import argparse class Uncount(argparse.Action): def __init__(self, option_strings, dest, nargs=0, choices=None, const=None, **kwargs): if nargs != 0: raise ValueError("no arguments to this parameter are allowed") if const is not None: raise ValueError("this parameter does not permit constants") if choices is not None: raise ValueError("no choices to this parameter are allowed") super(Uncount, self).__init__(option_strings=option_strings, nargs=nargs, dest=dest,**kwargs) def __call__(self, parser, namespace, values, option_string=None): value = getattr(namespace, self.dest, 0) setattr(namespace, self.dest, value-1) opts=<> argparser = argparse.ArgumentParser(description='Report on other teams') argparser.add_argument( '-v','--verbose',dest='verbose',default=0,action='count', help='increase log level', ) argparser.add_argument( '-q','--quiet',dest='verbose',default=0,action=Uncount, help='increase log level', ) 
>>> argparser.parse_args('-q -q'.split()) Namespace(verbose=-2) >>> argparser.parse_args('-q -v'.split()) Namespace(verbose=0) >>> argparser.parse_args('-q -v -v'.split()) Namespace(verbose=1) 

Источник

Python argparse command line flags without arguments

which I take it means that it wants an argument value for the -w option. What’s the way of just accepting a flag? I’m finding http://docs.python.org/library/argparse.html rather opaque on this question.

If you just want 1 flag to your script, sys.argv would be a whole lot easier. Unless your specifically trying to learn argparse, which is a good because its a handy module to know.

5 Answers 5

As you have it, the argument w is expecting a value after -w on the command line. If you are just looking to flip a switch by setting a variable True or False , have a look here (specifically store_true and store_false)

import argparse parser = argparse.ArgumentParser() parser.add_argument('-w', action='store_true') 

where action=’store_true’ implies default=False .

Conversely, you could have action=’store_false’ , which implies default=True .

Adding a quick snippet to have it ready to execute:

Читайте также:  Css background size width heights

Source: myparser.py

import argparse parser = argparse.ArgumentParser(description="Flip a switch by setting a flag") parser.add_argument('-w', action='store_true') args = parser.parse_args() print args.w 
python myparser.py -w >> True 

Your script is right. But by default is of None type. So it considers true of any other value other than None is assigned to args.argument_name variable.

I would suggest you to add a action=»store_true». This would make the True/False type of flag. If used its True else False.

import argparse parser = argparse.ArgumentParser('parser-name') parser.add_argument("-f","--flag",action="store_true",help="just a flag argument") 

After parsing when checked with args.f it returns true,

args = parser.parse_args() print(args.f) 

If you are looking for a binary flag, then the argparse actions store_true or store_false provide exactly this. This approach is well explained in the accepted answer by @Jdog.

The official docs are also fairly clear. I would only complete the example with one line, so to make it very clear how the store_true / store_false act:

>>> parser = argparse.ArgumentParser() >>> parser.add_argument('--foo', action='store_true') >>> parser.add_argument('--fov', action='store_true') # this is not in the docs! >>> parser.add_argument('--bar', action='store_false') >>> parser.add_argument('--baz', action='store_false') >>> parser.parse_args('--foo --bar'.split()) # --baz and --fov are missing Out[4]: Namespace(bar=False, baz=True, foo=True, fov=False) # mind the fov=False 

A slightly more powerful approach is to use the count action. You typically have used this type of flag already when setting the verbosity level when running a command.

For example ssh ‘s verbose mode flag -v is a counter:

-v Verbose mode. Causes ssh to print debugging messages about its progress. This is helpful in debugging connection, authentication, and configuration problems. Multiple -v options increase the verbosity. The maximum is 3.

So if you run ssh it’s non verbose, ssh -v is slightly verbose and ssh -vvv is maximally verbose.

With argparse in python such a counter flag can be defined as follows:

parser.add_argument('--verbose', '-v', action='count', default=0) 

If you want to use it as a boolena ( True / False ) flag, then you need to cast args.verbose into a boolean. You can either do this explicitly yourself, or rely a conditional statement like if args.verbose: . .

Читайте также:  Php if statement syntax

Here is a full working example to illustrate how you can use the counter flag:

#!/usr/bin/env python3 # test.py import argparse parser = argparse.ArgumentParser() parser.add_argument('--verbose', '-v', action='count', default=0) args = parser.parse_args() if args.verbose: print('verbose') print(f'verbosity level: ') else: print('non-verbose') 

You get the following outputs:

python test.py >> non-verbose 
python test.py -v >> verbose >> verbosity level: 1 
python test.py -vvv >> verbose >> verbosity level: 3 

Источник

python argument with or without value, specified or not

Scenario is as follows: I need to implement a command line argument system that allows both -p and -p (no value for -p given) Is there any way to achieve this using argparse, or will I have to manually parse sys.argv? Thank u so much.

2 Answers 2

What you need is three states, absent, present, present with value.

The argparse module provides at least two simple ways to do this.

For the simplest, and most flexible, you only need add action=’store’ and nargs=’*’.

#!/usr/bin/python import argparse parser = argparse.ArgumentParser() parser.add_argument('-p', action='store', nargs='*') args = parser.parse_args() if args.p is not None: print( '-p present' ) else: print( '-p not present' ) print( '-p value', args.p ) 

Here is your output for this method:

# ./testpar.py -p not present -p value None # ./testpar.py -p -p present -p value [] # ./testpar.py -p something -p present -p value ['something'] # ./testpar.py -p something anotherthing -p present -p value ['something', 'anotherthing'] 

For the second method, you can set a specific value for the second of the three states, const=somevalue and nargs=’?’. This method supports one value only, and the value for ‘const’ has to be something that would not be a valid input by the user.

#!/usr/bin/python import argparse parser = argparse.ArgumentParser() parser.add_argument('-p', action='store', const='NoValue', nargs='?') args = parser.parse_args() if args.p: print( '-p present' ) else: print( '-p not present' ) print( '-p value', args.p ) 

And here is your output for the three cases,

# ./testpar.py -p not present -p value None # ./testpar.py -p -p present -p value NoValue # ./testpar.py -p something -p present -p value something 

Источник

Оцените статью