77

Can I use argparse to read named command line arguments that do not need to be in a specific order? I browsed through the documentation but most of it focused on displaying content based on the arguments provided (such as --h).

Right now, my script reads ordered, unnamed arguments:

myscript.py foo-val bar-val

using sys.argv:

foo = sys.argv[1]
bar = sys.argv[2]

But I would like to change the input so that it is order agnostic by naming arguments:

myscript.py --bar=bar-val --foo=foo-val

amphibient
  • 29,770
  • 54
  • 146
  • 240

3 Answers3

125

You can use the Optional Arguments like so.

With this program:

#!/usr/bin/env python3

import argparse, sys

parser=argparse.ArgumentParser()

parser.add_argument("--bar", help="Do the bar option")
parser.add_argument("--foo", help="Foo the program")

args=parser.parse_args()

print(f"Args: {args}\nCommand Line: {sys.argv}\nfoo: {args.foo}")
print(f"Dict format: {vars(args)}")

Make it executable:

$ chmod +x prog.py

Then if you call it with:

$ ./prog.py --bar=bar-val --foo foo-val

It prints:

Args: Namespace(bar='bar-val', foo='foo-val')
Command Line: ['./prog.py', '--bar=bar-val', '--foo', 'foo-val']
foo: foo-val
Dict format: {'bar': 'bar-val', 'foo': 'foo-val'}

Or, if the user wants help argparse builds that too:

 $ ./prog.py -h
usage: prog.py [-h] [--bar BAR] [--foo FOO]

options:
  -h, --help  show this help message and exit
  --bar BAR   Do the bar option
  --foo FOO   Foo the program

2022-08-30: Updated to Python3 this answer...

dawg
  • 98,345
  • 23
  • 131
  • 206
  • 2
    how do I read the value of `foo` after the args have been loaded ? – amphibient Oct 12 '16 at 15:30
  • 1
    is there like `args.get('foo')` ? – amphibient Oct 12 '16 at 15:30
  • 10
    Use `args.bar` to read `--bar` It will return `None` if not included in the command. You can also use a default instead. – dawg Oct 12 '16 at 15:33
  • 1
    Using python 3.5.1, and when not included it doesn't return `None`; it gives an error. So as an alternative, `d = vars(args)` gives a dictionary (maps named arguments to values) – DZack Nov 13 '17 at 18:12
  • @MikhailV: Just to show what was on the command line prior to processing with the `print sys` at the end. – dawg May 04 '18 at 14:42
  • @dawg ah,ok. In python 3 it does not work. It works with `print (sys.argv)`. – Mikhail V May 04 '18 at 18:32
40

The answer is yes. A quick look at the argparse documentation would have answered as well.

Here is a very simple example, argparse is able to handle far more specific needs.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--foo', '-f', help="a random options", type= str)
parser.add_argument('--bar', '-b', help="a more random option", type= int, default= 0)

print(parser.format_help())
# usage: test_args_4.py [-h] [--foo FOO] [--bar BAR]
# 
# optional arguments:
#   -h, --help         show this help message and exit
#   --foo FOO, -f FOO  a random options
#   --bar BAR, -b BAR  a more random option

args = parser.parse_args("--foo pouet".split())
print(args)  # Namespace(bar=0, foo='pouet')
print(args.foo) # pouet
print(args.bar) # 0

Off course, in a real script, you won't hard-code the command-line options and will call parser.parse_args() (without argument) instead. It will make argparse take the sys.args list as command-line arguments.

You will be able to call this script this way:

test_args_4.py -h  # prints the help message
test_args_4.py -f pouet  # foo="pouet", bar=0 (default value)
test_args_4.py -b 42  # foo=None, bar=42
test_args_4.py -b 77 -f knock  # foo="knock", bar=77

You will discover a lot of other features by reading the doc ;)

Tryph
  • 5,946
  • 28
  • 49
  • but in your script, you don't know that 'pouet' is passed as the arg value – amphibient Oct 12 '16 at 15:23
  • in line `args = parser.parse_args("--foo pouet".split())`, why do you hard code what argument value the script should read rather than reading whatever was supplied by the command ? – amphibient Oct 12 '16 at 15:33
  • 1
    @amphibient This is an example to show you how to access the arguments values then. in a real script, you will just call `parser.parse_args()` with no argument and it will take the `sys.args` list – Tryph Oct 12 '16 at 15:35
2

I think it might help you with a simple one

#! /usr/bin/python3                                                                                                                    
import sys                                                                                                                             
                                                                                                                                   
keys = ["--paramkey=","-p="]                                                                                                           
for i in range(1,len(sys.argv)):                                                                                                       
    for key in keys:                                                                                                                   
        if sys.argv[i].find(key) == 0:                                                                                                 
            print(f"The Given value is: {sys.argv[i][len(key):]}")                                                                     
            break   

Run:

$ ./example.py --paramkey=paramvalue -p=pvalue

Output:

The Given value is: paramvalue
The Given value is: pvalue