user7186882 user7186882 - 14 days ago 5
Python Question

Python argparse versatility ability for true/false and string?

I have the following arguments parser using argparse in a python 2.7 script:

parser = argparse.ArgumentParser(description=scriptdesc)
parser.add_argument("-l", "--list", help="Show current running sesssions", dest="l_list", type=str, default=None)


I want to be able to run:


./script -l and ./script -l session_1


So that the script returns either all sessions or a single session without an extra parameter such as -s

However I can't find a way to do this in a single arg.

Answer

This is a bit of a hack since it relies on accessing sys.argv outside of any argparse function but you can do something like:

import argparse
import sys


parser = argparse.ArgumentParser(description='')
parser.add_argument("-l", "--list", help="Show current running sesssions", dest="l_list", nargs='?')
args = parser.parse_args()

if args.l_list == None:
    if '-l' in sys.argv or '--list' in sys.argv:
        print('display all')
else:
    print('display %s only' %args.l_list)

And you would obviously replace the print statements with your actual code. This works by allowing 0 or 1 argument (using nargs='?'). This allows you to either pass an argument with -l or not. This means that in the args namespace, l_list can be None (the default) if you call -l without an argument OR if you don't use -l at all. Then later you can check if -l was called without an argument (if l_list == None and -l or --list is in sys.argv).

If I name this script test.py I get the following outputs when calling it from the command line.

$python test.py
$python test.py -l
display all
$python test.py -l session1
display session1 only

EDIT

I figured out an argparse only solution!! No relying on sys.argv:

import argparse

parser = argparse.ArgumentParser(description='')
parser.add_argument("-l", "--list", help="Show current running sesssions", dest="l_list", nargs='?', default=-1)
args = parser.parse_args()

if args.l_list == None:
    print('display all')
elif args.l_list != -1:
    print('display %s only' %args.l_list)

So it turns out that the default keyword in .add_argument only applies when the argument flag is not called at all. If the flag is used without anything following it, it will default to None regardless of what the default keyword is. So if we set the default to something that is not None and not an expected argument value (in this case I chose -1), then we can handle all three of your cases:

$ python test.py
$ python test.py -l
display all
$ python test.py -l session1
display session1 only
Comments