mrQWERTY
mrQWERTY

Reputation: 4149

Passing in multiple options for argparse in Python

I have been looking at argparse documentation but I am still confused how to use it. I made a python script to get issues from either pmd, checkstyle, or findbugs after a code analysis. Theses issues are also categorized into severities such as major, blocker, and critical.

So I want to be able to pass in two arguments in the form python script.py arg1 arg2 where arg1 would be a combination of p,c,f which stands for pmd, checkstyle, or findbug and arg2 would be a combination of m,c,b which stands for major, critical, and blocker.

So for instance, if I write python script.py pf cb in the terminal, I would get pmd and findbugs issues of critical and blocker severity.

It would be awesome if someone can give me a general structure of how this should go.

Thanks.

Upvotes: 3

Views: 1267

Answers (3)

hpaulj
hpaulj

Reputation: 231385

https://stackoverflow.com/users/1401034/ewan is a good solution given your specification. But a slight variation gives users more options, and might be clearer.

parser = argparse.ArgumentParser()
parser.add_argument('-p', '--pmd', action='store_true')
parser.add_argument('-c', '--checkstyle', action='store_true')
parser.add_argument('-f', '--findbug', action='store_true')
parser.add_argument('-m', '--major', action='store_true')
parser.add_argument('-d', '--critical', action='store_true')
parser.add_argument('-b', '--blocker', action='store_true')

args = parser.parse_args()
print args

Sample runs:

1840:~/mypy$ python2.7 stack24265375.py -cfmd
Namespace(blocker=False, checkstyle=True, critical=True, findbug=True, major=True, pmd=False)
1841:~/mypy$ python2.7 stack24265375.py -h
usage: stack24265375.py [-h] [-p] [-c] [-f] [-m] [-d] [-b]

optional arguments:
  -h, --help        show this help message and exit
  -p, --pmd
  -c, --checkstyle
  -f, --findbug
  -m, --major
  -d, --critical
  -b, --blocker
1842:~/mypy$ python2.7 stack24265375.py --critical --major
Namespace(blocker=False, checkstyle=False, critical=True, findbug=False, major=True, pmd=False)

In this case, there are 6 optional, boolean flags. The short, single letter versions can be strung together in any combination. Except the necessary '-', this form can look just like the one using 2 positional arguments. But they can be mixed and matched in any combination. And the long form is self documenting.

The help display might be clearer if these 6 arguments were divided into 2 argument groups.

parser = argparse.ArgumentParser()
group1 = parser.add_argument_group('issue')
group1.add_argument('-p', '--pmd', action='store_true')
group1.add_argument('-c', '--checkstyle', action='store_true')
group1.add_argument('-f', '--findbug', action='store_true')
group2 = parser.add_argument_group('severity')
group2.add_argument('-m', '--major', action='store_true')
group2.add_argument('-d', '--critical', action='store_true')
group2.add_argument('-b', '--blocker', action='store_true')

args = parser.parse_args()
print args

with the help:

usage: stack24265375.py [-h] [-p] [-c] [-f] [-m] [-d] [-b]

optional arguments:
  -h, --help        show this help message and exit

issue:
  -p, --pmd
  -c, --checkstyle
  -f, --findbug

severity:
  -m, --major
  -d, --critical
  -b, --blocker

Upvotes: 2

Mattias Backman
Mattias Backman

Reputation: 955

Perhaps you'd rather let the user specify the flags more verbose, like this?

python script.py --checker p --checker f --level c --level b

If so, you can use append

>>> parser = argparse.ArgumentParser()
>>> parser.add_argument('--checker', action='append')
>>> parser.add_argument('--level', action='append')

Then you get a parameter checker and level, both as lists to iterate over.

If you really want to use the combined flags:

for c in arg1:
    run_checker(c, arg2)

Assuming that you just pass the severity levels to the checker in some way.

Upvotes: 3

Ewan
Ewan

Reputation: 15058

You could try setting boolean flags if each option is present in an argument:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument("pcf", help="pmd, checkstyle, or findbug")
parser.add_argument("mcb", help="major, critical, and blocker")
args = parser.parse_args()

# Use boolean flags
pmd  = 'p' in args.pcf
checkstyle = 'c' in args.pcf
findbug = 'f' in args.pcf

major = 'm' in args.mcb
critical = 'c' in args.mcb
blocker = 'b' in args.mcb

This would work using python script.py pf cb.

Also, just a helpful hint. If you place the following at the top of your python file and then make it executable with chmod +x script.py you can then call the file directly (using a *NIX operating system):

#!/usr/bin/env python
import argparse

...

Now run with ./script.py pf cb or even put it in your path and call script.py pf cb

Upvotes: 2

Related Questions