Argparse optional positional arguments?
Use nargs='?'
(or nargs='*'
if you need more than one dir)
parser.add_argument('dir', nargs='?', default=os.getcwd())
extended example:
>>> import os, argparse
>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('-v', action='store_true')
_StoreTrueAction(option_strings=['-v'], dest='v', nargs=0, const=True, default=False, type=None, choices=None, help=None, metavar=None)
>>> parser.add_argument('dir', nargs='?', default=os.getcwd())
_StoreAction(option_strings=[], dest='dir', nargs='?', const=None, default='/home/vinay', type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args('somedir -v'.split())
Namespace(dir='somedir', v=True)
>>> parser.parse_args('-v'.split())
Namespace(dir='/home/vinay', v=True)
>>> parser.parse_args(''.split())
Namespace(dir='/home/vinay', v=False)
>>> parser.parse_args(['somedir'])
Namespace(dir='somedir', v=False)
>>> parser.parse_args('somedir -h -v'.split())
usage: [-h] [-v] [dir]
positional arguments:
dir
optional arguments:
-h, --help show this help message and exit
-v
Argparse value for optional positional argument
I can't tell if the optional argument was not defined, or was defined but without a value
If you create your parser like this:
parser = argparse.ArgumentParser(argument_default=argparse.SUPPRESS)
Now it is possible to distinguish between the three cases.
- If
-c val
was passed, it will be present inargs
with value"val"
. - If
-c
was passed without value, it will be present inargs
with valueNone
. - If
-c
was omitted entirely, it won't be present inargs
.
The same goes for -p
.
If you only want this suppression to apply for one option, rather than on the whole parser, that is possible too:
parser.add_argument('-c', '--csv', nargs='?', default=argparse.SUPPRESS)
Optional positional arguments with Python's argparse
This is a limitation of argparse—but one that's partially lifted in 3.7.
Unix tools generally don't claim to support intermixing of options and arguments, even though they often do. The problem is that combining it with some other features, like subcommands, leads to ambiguity. So, typically, libraries that support any of those features punt on the problem and don't allow intermixing. Or they do something kind of hacky—allowing options at the end, at the start, and in certain hard-to-predict cases but not others in the middle.
That's what argparse
originally did. But 3.7 adds Intermixed parsing.
You have to manually call parse_intermixed_args
instead of parse_args
.
And if you try to use this with any of the features it doesn't go well with, you'll get an exception (even if there's no ambiguity for the particular set of args you pass—which should make it easier to debug).
But otherwise, it'll work as expected: options (together with their values, of course) can be freely mixed with positional arguments anywhere in the command line.
Unfortunately, I don't know of a drop-in backport on PyPI to get 3.7 argparse
in earlier versions; the semi-official argparse
backport is mainly for pre-2.7/3.2 versions that don't have it at all, and only backports the 3.4 version.
How to use sub-commands along with optional positional arguments in argparse
You're looking for the action='store_true'
property on the argument specification.
https://docs.python.org/3/library/argparse.html#action
parser.add_argument('-d', '--display', dest='disp',
action='store_true', help='Opens a webpage')
#main.py
import os, numpy
import argparse
import webbrowser
new=2
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-i','--input',type=str, help='Choose input')
parser.add_argument('-d','--display',dest='disp', action='store_true', help='Opens a webpage')
args = parser.parse_args()
if args.input == 'infile':
print('This is input file')
if args.disp:
url = "https://stackoverflow.com/"
webbrowser.open(url,new=new,autoraise=True)
if __name__=='__main__':
main()
argparse: optional argument between positional arguments
Starting from Python 3.7, it seems argparse
now supports this kind of Unix-style parsing:
Intermixed parsing
ArgumentParser.parse_intermixed_args(args=None, namespace=None)
A number of Unix commands allow the user to intermix optional arguments with positional arguments. The
parse_intermixed_args()
andparse_known_intermixed_args()
methods support this parsing style.
There is a caveat, but for "simple" options, it does not affect them:
These parsers do not support all the argparse features, and will raise exceptions if unsupported features are used. In particular, subparsers,
argparse.REMAINDER
, and mutually exclusive groups that include both optionals and positionals are not supported.
(I posted this FAQ-style question after spending 1 hour trying to understand why the examples in the Python argparse
documentation didn't seem to include it, and only by chance found a somewhat unrelated question which contained the mention to this "intermixed" function in a comment, which I am unable to find again to cite it properly.)
Optional positional argument, that only accepts values from a specified list
You can use the add_argument
method once for each option in your list, supplying the whole list as possible choices for each argument, and then use the '?' for the nargs
field
for example here:
import sys
import argparse
parser = argparse.ArgumentParser(sys.argv[0])
choices = ["A", "B", "C", "D", "E"]
for i, choice in enumerate(choices):
parser.add_argument(choice, metavar=choice,
help="Help Message For Choice" + choice,
choices=choices, nargs='?')
args = parser.parse_args()
This will accept 0, 1, 2, ... len(choices)
arguments. You will probably want to override the usage string if you go this route.
python3 name_of_pythonfile.py -h
usage: name_of_pythonfile.py [-h] [A] [B] [C] [D] [E]
positional arguments:
A Help Message for ChoiceA
B Help Message for ChoiceB
C Help Message for ChoiceC
D Help Message for ChoiceD
E Help Message for ChoiceE
options:
-h, --help show this help message and exit
To override the default usage message you just need to pass a string to the usage keyword argument in the ArgumentParser constructor.
parser = ArgumentParser(prog, usage="My New Usage String")
argparse docs
Argparse: Required arguments listed under optional arguments?
Parameters starting with -
or --
are usually considered optional. All other parameters are positional parameters and as such required by design (like positional function arguments). It is possible to require optional arguments, but this is a bit against their design. Since they are still part of the non-positional arguments, they will still be listed under the confusing header “optional arguments” even if they are required. The missing square brackets in the usage part however show that they are indeed required.
See also the documentation:
In general, the argparse module assumes that flags like -f and --bar indicate optional arguments, which can always be omitted at the command line.
Note: Required options are generally considered bad form because users expect options to be optional, and thus they should be avoided when possible.
That being said, the headers “positional arguments” and “optional arguments” in the help are generated by two argument groups in which the arguments are automatically separated into. Now, you could “hack into it” and change the name of the optional ones, but a far more elegant solution would be to create another group for “required named arguments” (or whatever you want to call them):
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('-o', '--output', help='Output file name', default='stdout')
requiredNamed = parser.add_argument_group('required named arguments')
requiredNamed.add_argument('-i', '--input', help='Input file name', required=True)
parser.parse_args(['-h'])
usage: [-h] [-o OUTPUT] -i INPUT
Foo
optional arguments:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
Output file name
required named arguments:
-i INPUT, --input INPUT
Input file name
Related Topics
Python - Pygame Error When Executing Exe File
How to Manage Third-Party Python Libraries with Google App Engine? (Virtualenv? Pip)
Python, Https Get with Basic Authentication
Force Numpy Ndarray to Take Ownership of Its Memory in Cython
How to Change Dataframe Column Names in Pyspark
How to Trigger Function on Value Change
How to Share Variables Across Scripts in Python
Tkinter Vanishing Photoimage Issue
How to Normalize a Numpy Array to a Unit Vector
How to Dynamically Add/Remove Periodic Tasks to Celery (Celerybeat)
List of Dicts To/From Dict of Lists
Not All Parameters Were Used in the SQL Statement (Python, MySQL)
Why Is Tensorflow 2 Much Slower Than Tensorflow 1