Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Argparse: Making required flags

I am attempting to create a required flag "-f" that accepts the input "filename.pdb" in Argparse.

This is simple enough. The standard solution is to add the option "required=True."

Unfortunately, after doing this, the "-f" flag still appears under optional arguments in the help list. Even more confusingly, the "-f" flag appears as required in the "usage" prompt in the help list.

Here is my code:

parser = argparse.ArgumentParser()

parser.add_argument("-f", "--file_name", required=True, help="enter name of .pdb file")

parser.add_argument("-bw", "--bin_width",  default=.25, help="enter desired bin width in nanometers. default = .25")

parser.add_argument("-bn","--base_name", default="IDP", help="custom prefix for output file naming. default = IDP")

args = parser.parse_args()   

And here is the help window that is returned by --help

usage: rgcalc.py [-h] -f FILE_NAME [-bw BIN_WIDTH] [-bn BASE_NAME]

optional arguments:
  -h, --help            show this help message and exit
  -f FILE_NAME, --file_name FILE_NAME
                    enter name of .pdb file
  -bw BIN_WIDTH, --bin_width BIN_WIDTH
                    enter desired bin width in nanometers. default = .25
  -bn BASE_NAME, --base_name BASE_NAME
                    custom prefix for output file naming. default = IDP

As you can see in the "usage" block, "-f" has been taken out of brackets, indicating that it is required. Despite this, "-f" still appears in the "optional arguments" section.

Is it possible to:

A) Custom format the help window to fix this

or

B) Add some code to have the flag "-f", "--file_name" appear as a positional (opposed to an optional) argument, yet still require a flag?

I read that Argparse intentionally did this to avoid positional flags, but I am supposed to do it in order to cater to traditional linux users.

Thank you kind interwebbers!

like image 744
Jacob C Boswell Avatar asked Oct 07 '14 00:10

Jacob C Boswell


People also ask

How do you make an argument mandatory in Python?

required is a parameter of the ArugmentParser object's function add_argument() . By default, the arguments of type -f or --foo are optional and can be omitted. If a user is required to make an argument, they can set the keyword argument required to True .

How do you add an optional argument in Argparse?

To add an optional argument, simply omit the required parameter in add_argument() . args = parser. parse_args()if args.

Is Argparse necessary?

The argparse is a standard module; we do not need to install it. A parser is created with ArgumentParser and a new parameter is added with add_argument .


1 Answers

This issue has been discussed in http://bugs.python.org/issue9694, 'argparse required arguments displayed under "optional arguments"'

It's a terminology issue that isn't easily resolved, due to historical practice (in UNIX as well as Python), and a lack of good alternatives.

Arguments that take a 'flag' like '-f' have historically been called options or optionals. Generally you don't use them unless you want some value that is different from the default. But 'argparse' lets you specify required=True, so now you have a 'required optional'. And with nargs='?', it is possible to have 'positionals' which are not required.

Until Python developers come up with some alternative terminology, your best choice is to use an 'ArgumentGroup', with the title and description that you like. By default the parser has 2 ArgumentGroups, 'optional arguments' and 'positional arguments'. It has to put the argument in one or the other. You can create others, and populate them as you wish.

see http://bugs.python.org/issue9694#msg132327 (post by the original argparse developer).

The 'usage' line is the one that accurately describes how arguments are used and whether they are required or not. 'ArgumentGroups' don't affect usage or parsing. They just determine how the help lines are grouped.


For your code:

parser = argparse.ArgumentParser()
req_grp = parser.add_argument_group(title='Required Optional')
req_grp.add_argument("-f", "--file_name", required=True, help="enter name of .pdb file")
parser.add_argument("-bw", "--bin_width",  default=.25, help="enter desired bin width in nanometers. default = .25")
parser.add_argument("-bn","--base_name", default="IDP", help="custom prefix for output file naming. default = IDP")
args = parser.parse_args()

"""
usage: stack26227536.py [-h] -f FILE_NAME [-bw BIN_WIDTH] [-bn BASE_NAME]

optional arguments:
  -h, --help            show this help message and exit
  -bw BIN_WIDTH, --bin_width BIN_WIDTH
                        enter desired bin width in nanometers. default = .25
  -bn BASE_NAME, --base_name BASE_NAME
                        custom prefix for output file naming. default = IDP

Required Optional:
  -f FILE_NAME, --file_name FILE_NAME
                        enter name of .pdb file
"""

Compare this with the help produced by dropping the -f flag:

usage: stack26227536.py [-h] [-bw BIN_WIDTH] [-bn BASE_NAME] file_name

positional arguments:
  file_name             enter name of .pdb file

optional arguments:
  -h, --help            show this help message and exit
  -bw BIN_WIDTH, --bin_width BIN_WIDTH
                        enter desired bin width in nanometers. default = .25
  -bn BASE_NAME, --base_name BASE_NAME
                        custom prefix for output file naming. default = IDP
like image 200
hpaulj Avatar answered Sep 20 '22 17:09

hpaulj