How to have multiple args for a single option in argparse - python

I would like to allow a user to enter in multiple ids as an argument. For example, something like:
import argparse
parser = argparse.ArgumentParser(description='Dedupe assets based on group_id.')
parser.add_argument('--ids', nargs='?', default=None, type=int, help='Enter your ids')
parser.parse_args()
Yet when I enter in something like:
$ python test.py --ids 1 2 3 4
I get the following error:
test.py: error: unrecognized arguments: 2 3 4
What would be the proper way to allow/enter in multiple arguments for a single option?

you can use '+' rather than '?'.
import argparse
parser = argparse.ArgumentParser(description='Dedupe assets based on group_id.')
parser.add_argument('--ids', nargs='+', default=None, type=int, help='Enter your ids')
args = parser.parse_args()
print(args.ids)

Related

Argparse: exception for option required=True

I use the following code to parse argument to my script (simplified version):
import argparse
ap = argparse.ArgumentParser()
ap.add_argument("-l", "--library", required=True)
ap.add_argument("--csv2fasta", required=False)
args = vars(ap.parse_args())
For every way the script can be run, the -l/--library flag should be required (required=True), but is there a way that it can use the setting required=False when you only use the --csv2fasta flag?
You have to write your test after parsing arguments, here's what I do for such cases:
def parse_args():
ap = argparse.ArgumentParser()
ap.add_argument("-l", "--library")
ap.add_argument("--csv2fasta")
args = ap.parse_args()
if not args.library and not args.csv2fasta:
ap.error("--library is required unless you provide --csv2fasta argument")
return args
$ python3 test-args.py
usage: test-args.py [-h] [-l LIBRARY] [--csv2fasta CSV2FASTA]
test-args.py: error: --library is required unless you provide --csv2fasta argument
$ python3 test-args.py --csv2fasta value

Nargs='+' capturing too many arguments python

I am using argparse for command line arguments, where one argument is one or more .csv files:
parser = argparse.ArgumentParser(description='...')
parser.add_argument('csv', type=str, nargs='+', help='.csv file(s)'))
parser.add_argument('days', type=int, help='Number of days'))
args = parser.parse_args()
print(args.csv)
When running $ python Filename.py csv Filename.csv days 30, args.csv is ['csv', 'Filename.csv', 'days'], but I don't want to be capturing the csv and days arguments which surround the input csv files.
You can use
import argparse
parser = argparse.ArgumentParser(description='...')
parser.add_argument("csv", type=str, nargs='+', help='.csv file(s)')
parser.add_argument("days", type=int, help='Number of days')
args = parser.parse_args()
print(args.csv)
Invoked with e.g. python your_script.py test.csv 100 this yields
['test.csv']
Note that you do not need to encapsulate parser.add_argument(...) twice (as you had in your code).

Python argparse how to add related group of options that are optional

I'm trying to add a group of options related to each other to existing script that has optional arguments and positional arguments to chose command to run.
import argparse
parser = argparse.ArgumentParser(prog='test')
parser.add_argument("-opt1", default="A", type=str)
parser.add_argument("-opt2", default="B", type=str)
parser.add_argument("-opt3", default="C", type=str)
subparsers = parser.add_subparsers()
cmd1 = subparsers.add_parser("cmd1", help="run cmd1")
cmd1.add_argument("-cmd1-opt1", default="cmd1-A")
cmd1.add_argument("-cmd1-opt2", default="cmd1-B")
cmd2 = subparsers.add_parser("cmd2", help="run cmd2")
cmd2.add_argument("-cmd2-opt", type=int)
args = parser.parse_args()
print(args)
For example I would like to add group of new optional options opt4, opt5, opt6, opt7 which are related.
Something like opt5 is valid option only when opt4 has some value.
I could add all the options individually as optional arguments but I'm looking for any better way to do that being the options I want to add are related to each other.

Python 3: Parse nested secondary arguments for initial set of choices

Subcommands like git commit and git status can be easily parsed with argparse using add_subparsers. How does one get nested settings input for choices selected from command line?
Let's say I want to play music with all custom settings:
play.py --path /path/to.file --duration 100 --filter equalizer --effect echo equalizer_settings 1 2 echo_settings 5
Here --filter equalizer and --effect echo are first level choices but I need to get settings for those as secondary arguments. Ex: echo_settings 5 and equalizer_settings 1 2.
Secondary settings could be more than one and preferably with named arguments.
Listed below is what I have so far...
import argparse
parser = argparse.ArgumentParser(description='Play music the way I want it.')
parser.add_argument('-p', '--path', type=str, required=True, help='File path')
parser.add_argument('-d', '--duration', type=int, default=50, help='Play duration')
parser.add_argument('-f', '--filter', choices=['none', 'equalizer'], default='none', help='Filter selection')
parser.add_argument('-e', '--effect', choices=['none', 'echo', 'surround'], default='none', help='Effect selection')
subparsers = parser.add_subparsers(help='Settings of optional parameters')
equalizer_parser = subparsers.add_parser("equalizer_settings")
equalizer_parser.add_argument('equalizer_min_range', type=int)
equalizer_parser.add_argument('equalizer_max_range', type=int)
echo_parser = subparsers.add_parser("echo_settings")
echo_parser.add_argument('echo_strength', type=int)
surround_parser = subparsers.add_parser("surround_settings")
surround_parser.add_argument('surround_strength', type=int)
args = parser.parse_args()
print(args)
Currently this errors in error: unrecognized arguments
You can only use one subparser at a time, i.e. one of those 3 settings. There are some advanced ways of using several subparsers in sequence, but I don't think we want to go there (see previous SO argparse questions).
But do you really need to use subparsers? Why not just another set of optionals (flagged) arguments, something like:
parser.add_argument("--equalizer_settings", nargs=2, type=int)
parser.add_argument("--echo_settings", type=int)
parser.add_argument("--surround_strength", type=int
You are just adding some parameters, not invoking some sort of action command.

Using argparse with a specified acceptable option

I am trying to use argparse to accept required command line options. I have defined a function like so
def get_args():
parser = argparse.ArgumentParser(description='Help Desk Calendar Tool')
parser.add_argument('-s', '--start', type=str, required=True, metavar='YYYY-MM-DD')
parser.add_argument('-e','--end', type=str, required=True, metavar='YYYY-MM-DD')
parser.add_argument('-m','--mode', type=str, required=True , metavar='add|del')
args = parser.parse_args()
start = args.start
end = args.end
mode = args.mode
return start,end,mode
What I am trying to do is for the option --mode I would like it to ONLY accept an parameter of either add or del. I could do this from an if statement but was wondering if argparse has a built in way of accomplishing this task. I looked at nargs but wasn't too clear if that's the path I need to go down
I think you are asking about choices:
parser.add_argument('-m','--mode', type=str, required=True, choices=['add', 'del'])
Demo:
$ python test.py -s 10 -e 20 -m invalid
usage: test.py [-h] -m {add,del}
test.py: error: argument -m/--mode: invalid choice: 'invalid' (choose from 'add', 'del')

Categories