The documentation for the argparse python module, while excellent I'm sure, is too much for my tiny beginner brain to grasp right now. I don't need to do math on the command line or meddle with formatting lines on the screen or change option characters. All I want to do is "If arg is A, do this, if B do that, if none of the above show help and quit".

10

16 Answers

Here's the way I do it with argparse (with multiple args):

parser = argparse.ArgumentParser(description='Description of your program') parser.add_argument('-f','--foo', help='Description for foo argument', required=True) parser.add_argument('-b','--bar', help='Description for bar argument', required=True) args = vars(parser.parse_args()) 

args will be a dictionary containing the arguments:

if args['foo'] == 'Hello': # code here if args['bar'] == 'World': # code here 

In your case simply add only one argument.

10

My understanding of the original question is two-fold. First, in terms of the simplest possible argparse example, I'm surprised that I haven't seen it here. Of course, to be dead-simple, it's also all overhead with little power, but it might get you started.

import argparse parser = argparse.ArgumentParser() parser.add_argument("a") args = parser.parse_args() if args.a == 'magic.name': print 'You nailed it!' 

But this positional argument is now required. If you leave it out when invoking this program, you'll get an error about missing arguments. This leads me to the second part of the original question. Matt Wilkie seems to want a single optional argument without a named label (the --option labels). My suggestion would be to modify the code above as follows:

... parser.add_argument("a", nargs='?', default="check_string_for_empty") ... if args.a == 'check_string_for_empty': print 'I can tell that no argument was given and I can deal with that here.' elif args.a == 'magic.name': print 'You nailed it!' else: print args.a 

There may well be a more elegant solution, but this works and is minimalist.

5

The argparse documentation is reasonably good but leaves out a few useful details which might not be obvious. (@Diego Navarro already mentioned some of this but I'll try to expand on his answer slightly.) Basic usage is as follows:

parser = argparse.ArgumentParser() parser.add_argument('-f', '--my-foo', default='foobar') parser.add_argument('-b', '--bar-value', default=3.14) args = parser.parse_args() 

The object you get back from parse_args() is a 'Namespace' object: An object whose member variables are named after your command-line arguments. The Namespace object is how you access your arguments and the values associated with them:

args = parser.parse_args() print (args.my_foo) print (args.bar_value) 

(Note that argparse replaces '-' in your argument names with underscores when naming the variables.)

In many situations you may wish to use arguments simply as flags which take no value. You can add those in argparse like this:

parser.add_argument('--foo', action='store_true') parser.add_argument('--no-foo', action='store_false') 

The above will create variables named 'foo' with value True, and 'no_foo' with value False, respectively:

if (args.foo): print ("foo is true") if (args.no_foo is False): print ("nofoo is false") 

Note also that you can use the "required" option when adding an argument:

parser.add_argument('-o', '--output', required=True) 

That way if you omit this argument at the command line argparse will tell you it's missing and stop execution of your script.

Finally, note that it's possible to create a dict structure of your arguments using the vars function, if that makes life easier for you.

args = parser.parse_args() argsdict = vars(args) print (argsdict['my_foo']) print (argsdict['bar_value']) 

As you can see, vars returns a dict with your argument names as keys and their values as, er, values.

There are lots of other options and things you can do, but this should cover the most essential, common usage scenarios.

3

Matt is asking about positional parameters in argparse, and I agree that the Python documentation is lacking on this aspect. There's not a single, complete example in the ~20 odd pages that shows both parsing and using positional parameters.

None of the other answers here show a complete example of positional parameters, either, so here's a complete example:

# tested with python 2.7.1 import argparse parser = argparse.ArgumentParser(description="An argparse example") parser.add_argument('action', help='The action to take (e.g. install, remove, etc.)') parser.add_argument('foo-bar', help='Hyphens are cumbersome in positional arguments') args = parser.parse_args() if args.action == "install": print("You asked for installation") else: print("You asked for something other than installation") # The following do not work: # print(args.foo-bar) # print(args.foo_bar) # But this works: print(getattr(args, 'foo-bar')) 

The thing that threw me off is that argparse will convert the named argument "--foo-bar" into "foo_bar", but a positional parameter named "foo-bar" stays as "foo-bar", making it less obvious how to use it in your program.

Notice the two lines near the end of my example -- neither of those will work to get the value of the foo-bar positional param. The first one is obviously wrong (it's an arithmetic expression args.foo minus bar), but the second one doesn't work either:

AttributeError: 'Namespace' object has no attribute 'foo_bar' 

If you want to use the foo-bar attribute, you must use getattr, as seen in the last line of my example. What's crazy is that if you tried to use dest=foo_bar to change the property name to something that's easier to access, you'd get a really bizarre error message:

ValueError: dest supplied twice for positional argument 

Here's how the example above runs:

$ python test.py usage: test.py [-h] action foo-bar test.py: error: too few arguments $ python test.py -h usage: test.py [-h] action foo-bar An argparse example positional arguments: action The action to take (e.g. install, remove, etc.) foo-bar Hyphens are cumbersome in positional arguments optional arguments: -h, --help show this help message and exit $ python test.py install foo You asked for installation foo 
5

Yet another summary introduction, inspired by this post.

import argparse # define functions, classes, etc. # executes when your script is called from the command-line if __name__ == "__main__": parser = argparse.ArgumentParser() # # define each option with: parser.add_argument # args = parser.parse_args() # automatically looks at sys.argv # # access results with: args.argumentName # 

Arguments are defined with combinations of the following:

parser.add_argument( 'name', options... ) # positional argument parser.add_argument( '-x', options... ) # single-char flag parser.add_argument( '-x', '--long-name', options... ) # flag with long name 

Common options are:

  • help: description for this arg when --help is used.
  • default: default value if the arg is omitted.
  • type: if you expect a float or int (otherwise is str).
  • dest: give a different name to a flag (e.g. '-x', '--long-name', dest='longName').
    Note: by default --long-name is accessed with args.long_name
  • action: for special handling of certain arguments
    • store_true, store_false: for boolean args
      '--foo', action='store_true' => args.foo == True
    • store_const: to be used with option const
      '--foo', action='store_const', const=42 => args.foo == 42
    • count: for repeated options, as in ./myscript.py -vv
      '-v', action='count' => args.v == 2
    • append: for repeated options, as in ./myscript.py --foo 1 --foo 2
      '--foo', action='append' => args.foo == ['1', '2']
  • required: if a flag is required, or a positional argument is not.
  • nargs: for a flag to capture N args
    ./myscript.py --foo a b => args.foo = ['a', 'b']
  • choices: to restrict possible inputs (specify as list of strings, or ints if type=int).

Note the Argparse Tutorial in Python HOWTOs. It starts from most basic examples, like this one:

import argparse parser = argparse.ArgumentParser() parser.add_argument("square", type=int, help="display a square of a given number") args = parser.parse_args() print(args.square**2) 

and progresses to less basic ones.

There is an example with predefined choice for an option, like what is asked:

import argparse parser = argparse.ArgumentParser() parser.add_argument("square", type=int, help="display a square of a given number") parser.add_argument("-v", "--verbosity", type=int, choices=[0, 1, 2], help="increase output verbosity") args = parser.parse_args() answer = args.square**2 if args.verbosity == 2: print("the square of {} equals {}".format(args.square, answer)) elif args.verbosity == 1: print("{}^2 == {}".format(args.square, answer)) else: print(answer) 
1

Here's what I came up with in my learning project thanks mainly to @DMH...

Demo code:

import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument('-f', '--flag', action='store_true', default=False) # can 'store_false' for no-xxx flags parser.add_argument('-r', '--reqd', required=True) parser.add_argument('-o', '--opt', default='fallback') parser.add_argument('arg', nargs='*') # use '+' for 1 or more args (instead of 0 or more) parsed = parser.parse_args() # NOTE: args with '-' have it replaced with '_' print('Result:', vars(parsed)) print('parsed.reqd:', parsed.reqd) if __name__ == "__main__": main() 

This may have evolved and is available online: command-line.py

Script to give this code a workout: command-line-demo.sh

1

code file: argparseDemo.py

Simple: common case

  • name(abbr, full), with help
    import argparse argParser = argparse.ArgumentParser() argParser.add_argument("-n", "--name", help="your name") args = argParser.parse_args() print("args=%s" % args) print("args.name=%s" % args.name) 
    • call
      • python argparseDemo.py -n Crifan
      • python argparseDemo.py --name Crifan
    • output: args=Namespace(name='Crifan') and args.name=Crifan
  • type
    argParser.add_argument("-a", "--age", type=int, help="your current age") print("type(args.age)=%s" % type(args.age)) 
    • call: python argparseDemo.py --age 30
    • output: type(args.age)=<class 'int'> and args.age=30
  • required
    argParser.add_argument("-a", "--age", required=True, type=int, help="your current age") 
    • call: python argparseDemo.py
    • output: error argparseDemo.py: error: the following arguments are required: -a/--age
  • default
    argParser.add_argument("-a", "--age", type=int, default=20, help="your current age. Default is 20") 
    • call: python argparseDemo.py
    • output: args.age=20
  • choices
    argParser.add_argument("-f", "--love-fruit", choices=['apple', 'orange', 'banana'], help="your love fruits") 
    • call: python argparseDemo.py -f apple
    • output: args=Namespace(love_fruit='apple') and args.love_fruit=apple
  • multi args
    argParser.add_argument("-f", "--love-fruit", nargs=2, help="your love fruits") 
    • call: python argparseDemo.py -f apple orange
    • output: args.love_fruit=['apple', 'orange']

Detail

most simple: -x

  • code:

    import argparse argParser = argparse.ArgumentParser() argParser.add_argument("-a") # most simple -> got args.a, type is `str` args = argParser.parse_args() print("args.a=%s" % args.a) 
  • usage = run in command line

    python argparseDemo.py -a 30 
    • or: ./argparseDemo.py -a 30
      • makesure argparseDemo.py is executable
        • if not, add it: chmod +x argparseDemo.py
  • output

    args.a=30 
  • Note

    • default type is str
      • argParser.add_argument("-a") == argParser.add_argument("-a", type=str)
      • print("type(args.a)=%s" % type(args.a)) -> type(args.a)=<class 'str'>
    • args type is Namespace
      • print("type(args)=%s" % type(args)) -> type(args)=<class 'argparse.Namespace'>
    • args value is Namespace(a='30')
      • print("args=%s" % args) -> args=Namespace(a='30')
      • so we can call/use args.a

parameter name

full parameter name: --xxx

  • code
    argParser.add_argument("-a", "--age") 
  • usage
    • python argparseDemo.py -a 30
      • or: python argparseDemo.py --age 30
  • get parsed value: args.age
    • Note: NOT args.a, and NOT exist args.a

full parameter name with multiple words: --xxx-yyy

  • code
    argParser.add_argument("-a", "--current-age") 
  • get parsed value: args.current_age

add help description: help

  • code
    argParser.add_argument("-a", help="your age") # with help 
  • output
    • use --help can see description
       python argparseDemo.py --help usage: argparseDemo.py [-h] [-a A] optional arguments: -h, --help show this help message and exit -a A your age 

designate parameter type: type

  • code
    argParser.add_argument("-a", type=int) # parsed arg is `int`, not default `str` 
  • output
    • print("type(args.a)=%s" % type(args.a)) -> type(args.a)=<class 'int'>
    • print("args=%s" % args) -> args=Namespace(a=30)

add default value: default

  • code
    argParser.add_argument("-a", type=int, default=20) # if not pass a, a use default value: 20 
  • effect
    • usage: python argparseDemo.py
    • output: print("args.age=%s" % args.age) -> args=Namespace(a=20)

You could also use plac (a wrapper around argparse).

As a bonus it generates neat help instructions - see below.

Example script:

#!/usr/bin/env python3 def main( arg: ('Argument with two possible values', 'positional', None, None, ['A', 'B']) ): """General help for application""" if arg == 'A': print("Argument has value A") elif arg == 'B': print("Argument has value B") if __name__ == '__main__': import plac plac.call(main) 

Example output:

No arguments supplied - example.py:

usage: example.py [-h] {A,B} example.py: error: the following arguments are required: arg 

Unexpected argument supplied - example.py C:

usage: example.py [-h] {A,B} example.py: error: argument arg: invalid choice: 'C' (choose from 'A', 'B') 

Correct argument supplied - example.py A :

Argument has value A 

Full help menu (generated automatically) - example.py -h:

usage: example.py [-h] {A,B} General help for application positional arguments: {A,B} Argument with two possible values optional arguments: -h, --help show this help message and exit 

Short explanation:

The name of the argument usually equals the parameter name (arg).

The tuple annotation after arg parameter has the following meaning:

  • Description (Argument with two possible values)
  • Type of argument - one of 'flag', 'option' or 'positional' (positional)
  • Abbreviation (None)
  • Type of argument value - eg. float, string (None)
  • Restricted set of choices (['A', 'B'])

Documentation:

To learn more about using plac check out its great documentation:

Plac: Parsing the Command Line the Easy Way

To add to what others have stated:

I usually like to use the 'dest' parameter to specify a variable name and then use 'globals().update()' to put those variables in the global namespace.

Usage:

$ python script.py -i "Hello, World!" 

Code:

... parser.add_argument('-i', '--input', ..., dest='inputted_variable',...) globals().update(vars(parser.parse_args())) ... print(inputted_variable) # Prints "Hello, World!" 
1

I went through all the examples and answers and in a way or another they didn't address my need. So I will list her a scenario that I need more help and I hope this can explain the idea more.

Initial Problem

I need to develop a tool which is getting a file to process it and it needs some optional configuration file to be used to configure the tool.

so what I need is something like the following

mytool.py file.text -config config-file.json 

The solution

Here is the solution code

import argparse def main(): parser = argparse.ArgumentParser(description='This example for a tool to process a file and configure the tool using a config file.') parser.add_argument('filename', help="Input file either text, image or video") # parser.add_argument('config_file', help="a JSON file to load the initial configuration ") # parser.add_argument('-c', '--config_file', help="a JSON file to load the initial configuration ", default='configFile.json', required=False) parser.add_argument('-c', '--config', default='configFile.json', dest='config_file', help="a JSON file to load the initial configuration " ) parser.add_argument('-d', '--debug', action="store_true", help="Enable the debug mode for logging debug statements." ) args = parser.parse_args() filename = args.filename configfile = args.config_file print("The file to be processed is", filename) print("The config file is", configfile) if args.debug: print("Debug mode enabled") else: print("Debug mode disabled") print("and all arguments are: ", args) if __name__ == '__main__': main() 

I will show the solution in multiple enhancements to show the idea

First Round: List the arguments

List all input as mandatory inputs so second argument will be

parser.add_argument('config_file', help="a JSON file to load the initial configuration ") 

When we get the help command for this tool we find the following outcome

(base) > python .\argparser_example.py -h usage: argparser_example.py [-h] filename config_file This example for a tool to process a file and configure the tool using a config file. positional arguments: filename Input file either text, image or video config_file a JSON file to load the initial configuration optional arguments: -h, --help show this help message and exit 

and when I execute it as the following

(base) > python .\argparser_example.py filename.txt configfile.json 

the outcome will be

The file to be processed is filename.txt The config file is configfile.json and all arguments are: Namespace(config_file='configfile.json', filename='filename.txt') 

But the config file should be optional, I removed it from the arguments

(base) > python .\argparser_example.py filename.txt 

The outcome will be is:

usage: argparser_example.py [-h] filename config_file argparser_example.py: error: the following arguments are required: c 

Which means we have a problem in the tool

Second Round : Make it optimal

So to make it optional I modified the program as follows

 parser.add_argument('-c', '--config', help="a JSON file to load the initial configuration ", default='configFile.json', required=False) 

The help outcome should be

usage: argparser_example.py [-h] [-c CONFIG] filename This example for a tool to process a file and configure the tool using a config file. positional arguments: filename Input file either text, image or video optional arguments: -h, --help show this help message and exit -c CONFIG, --config CONFIG a JSON file to load the initial configuration 

so when I execute the program

(base) > python .\argparser_example.py filename.txt 

the outcome will be

The file to be processed is filename.txt The config file is configFile.json and all arguments are: Namespace(config_file='configFile.json', filename='filename.txt') 

with arguments like

(base) > python .\argparser_example.py filename.txt --config_file anotherConfig.json 

The outcome will be

The file to be processed is filename.txt The config file is anotherConfig.json and all arguments are: Namespace(config_file='anotherConfig.json', filename='filename.txt') 

Round 3: Enhancements

to change the flag name from --config_file to --config while we keep the variable name as is we modify the code to include dest='config_file' as the following:

parser.add_argument('-c', '--config', help="a JSON file to load the initial configuration ", default='configFile.json', dest='config_file') 

and the command will be

(base) > python .\argparser_example.py filename.txt --config anotherConfig.json 

To add the support for having a debug mode flag, we need to add a flag in the arguments to support a boolean debug flag. To implement it i added the following:

 parser.add_argument('-d', '--debug', action="store_true", help="Enable the debug mode for logging debug statements." ) 

the tool command will be:

(carnd-term1-38) > python .\argparser_example.py image.jpg -c imageConfig,json --debug 

the outcome will be

The file to be processed is image.jpg The config file is imageConfig,json Debug mode enabled and all arguments are: Namespace(config_file='imageConfig,json', debug=True, filename='image.jpg') 

New to this, but combining Python with Powershell and using this template, being inspired by an in-depth and great Python Command Line Arguments – Real Python

There is a lot you can do within the init_argparse() and I am covering just the most simple scenario here.

  1. import argparse
  2. use if __name__ == "__main__": main() pattern to execute from terminal
  3. parse arguments within the main() function that has no parameters as all
  4. define a init_argparse() function
    • create a parser object by calling argparse.ArgumentParser()
    • declare one or more argumnent with parser.add_argument("--<long_param_name>")
    • retur parser
  5. parse args by creating an args object by calling parser.parse_args()
  6. define a function proper with param1, param2, ...
  7. call function_proper with params being assigned as attributes of an args object
    • e.g. `function_proper(param1=args.param1, param2=args.param2)
  8. within a shell call the module with named arguments:
    • e.g. python foobar.py --param1="foo" --param2=="bar"
#file: foobar.py import argparse def function_proper(param1, param2): #CODE... def init_argparse() -> argparse.ArgumentParser: parser = argparse.ArgumentParser() parser.add_argument("--param1") parser.add_argument("--param2") return parser def main() -> None: parser = init_argparse() args = parser.parse_args() function_proper(param1=args.param1, param2=args.param2) if __name__ == "__main__": main() 
>>> python .\foobar.py --param1="foo" --param2=="bar" 

A really simple way to use argparse and amend the '-h'/ '--help' switches to display your own personal code help instructions is to set the default help to False, you can also add as many additional .add_arguments as you like:

import argparse parser = argparse.ArgumentParser(add_help=False) parser.add_argument('-h', '--help', action='help', help='To run this script please provide two arguments') parser.parse_args() 

Run: python test.py -h

Output:

usage: test.py [-h] optional arguments: -h, --help To run this script please provide two arguments 

Since you have not clarified wheather the arguments 'A' and 'B' are positional or optional, I'll make a mix of both.

Positional arguments are required by default. If not giving one will throw 'Few arguments given' which is not the case for the optional arguments going by their name. This program will take a number and return its square by default, if the cube option is used it shall return its cube.

import argparse parser = argparse.ArgumentParser('number-game') parser.add_argument( "number", type=int, help="enter a number" ) parser.add_argument( "-c", "--choice", choices=['square','cube'], help="choose what you need to do with the number" ) # all the results will be parsed by the parser and stored in args args = parser.parse_args() # if square is selected return the square, same for cube if args.c == 'square': print("{} is the result".format(args.number**2)) elif args.c == 'cube': print("{} is the result".format(args.number**3)) else: print("{} is not changed".format(args.number)) 

usage

$python3 script.py 4 -c square 16 

Here the optional arguments are taking value, if you just wanted to use it like a flag you can too. So by using -s for square and -c for cube we change the behaviour, by adding action = "store_true". It is changed to true only when used.

parser.add_argument( "-s", "--square", help="returns the square of number", action="store_true" ) parser.add_argument( "-c", "--cube", help="returns the cube of number", action="store_true" ) 

so the conditional block can be changed to,

if args.s: print("{} is the result".format(args.number**2)) elif args.c: print("{} is the result".format(args.number**3)) else: print("{} is not changed".format(args.number)) 

usage

$python3 script.py 4 -c 64 

As an addition to existing answers, if you are lazy enough, it is possible to use code generation tool called protoargs. It generates arguments parser from the configuration. For python it uses argparse.

Configuration with optional A and B:

syntax = "proto2"; message protoargs { optional string A = 1; // A param description optional string B = 2; // B param description }//protoargs 

Configuration with required A and B:

syntax = "proto2"; message protoargs { required string A = 1; // A param description required string B = 2; // B param description }//protoargs 

Configuration with positional A and B:

syntax = "proto2"; message protoargs { required string A = 1; // A param description required string B = 2; // B param description }//protoargs message protoargs_links { }//protoargs_links 

Now all you should run is:

python ./protoargs.py -i test.proto -o . --py 

And use it (it is possible to take other examples here):

import sys import test_pa class ArgsParser: program = "test" description = "Simple A and B parser test." def parse(self, argv): self.config = test_pa.parse(self.program, self.description, argv) def usage(self): return test_pa.usage(self.program, self.description) if __name__ == "__main__": parser = ArgsParser() if len(sys.argv) == 1: print(parser.usage()) else: parser.parse(sys.argv[1:]) if parser.config.A: print(parser.config.A) if parser.config.B: print(parser.config.B) 

If you want more - change configuration, regenerate parser, use an updated parser.config.

UPD: As mentioned in rules, I must specify that this is my own project

The simplest answer!

P.S. the one who wrote the document of argparse is foolish

python code:

import argparse parser = argparse.ArgumentParser(description='') parser.add_argument('--o_dct_fname',type=str) parser.add_argument('--tp',type=str) parser.add_argument('--new_res_set',type=int) args = parser.parse_args() o_dct_fname = args.o_dct_fname tp = args.tp new_res_set = args.new_res_set 

running code

python produce_result.py --o_dct_fname o_dct --tp father_child --new_res_set 1 
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy