Home » Python » What's the best way to grab/parse command line arguments passed to a Python script?

What's the best way to grab/parse command line arguments passed to a Python script?

Posted by: admin November 1, 2017 Leave a comment


What’s the easiest, tersest, and most flexible method or library for parsing Python command line arguments?


This answer suggests optparse which is appropriate for older Python versions. For Python 2.7 and above, argparse replaces optparse. See this answer for more information.

As other people pointed out, you are better off going with optparse over getopt. getopt is pretty much a one-to-one mapping of the standard getopt(3) C library functions, and not very easy to use.

optparse, while being a bit more verbose, is much better structured and simpler to extend later on.

Here’s a typical line to add an option to your parser:

parser.add_option('-q', '--query',
            action="store", dest="query",
            help="query string", default="spam")

It pretty much speaks for itself; at processing time, it will accept -q or –query as options, store the argument in an attribute called query and has a default value if you don’t specify it. It is also self-documenting in that you declare the help argument (which will be used when run with -h/–help) right there with the option.

Usually you parse your arguments with:

options, args = parser.parse_args()

This will, by default, parse the standard arguments passed to the script (sys.argv[1:])

options.query will then be set to the value you passed to the script.

You create a parser simply by doing

parser = optparse.OptionParser()

These are all the basics you need. Here’s a complete Python script that shows this:

import optparse

parser = optparse.OptionParser()

parser.add_option('-q', '--query',
    action="store", dest="query",
    help="query string", default="spam")

options, args = parser.parse_args()

print 'Query string:', options.query

5 lines of python that show you the basics.

Save it in sample.py, and run it once with

python sample.py

and once with

python sample.py --query myquery

Beyond that, you will find that optparse is very easy to extend.
In one of my projects, I created a Command class which allows you to nest subcommands in a command tree easily. It uses optparse heavily to chain commands together. It’s not something I can easily explain in a few lines, but feel free to browse around in my repository for the main class, as well as a class that uses it and the option parser


Other answers do mention that argparse is the way to go for new Python, but do not give usage examples. For completeness, here is a short summary of how to use argparse:

1) Initialize

import argparse

# Instantiate the parser
parser = argparse.ArgumentParser(description='Optional app description')

2) Add Arguments

# Required positional argument
parser.add_argument('pos_arg', type=int,
                    help='A required integer positional argument')

# Optional positional argument
parser.add_argument('opt_pos_arg', type=int, nargs='?',
                    help='An optional integer positional argument')

# Optional argument
parser.add_argument('--opt_arg', type=int,
                    help='An optional integer argument')

# Switch
parser.add_argument('--switch', action='store_true',
                    help='A boolean switch')

3) Parse

args = parser.parse_args()

4) Access

print("Argument values:")

5) Check Values

if args.pos_arg > 10:
    parser.error("pos_arg cannot be larger than 10")


Correct use:

$ ./app 1 2 --opt_arg 3 --switch

Argument values:

Incorrect arguments:

$ ./app foo 2 --opt_arg 3 --switch
usage: convert [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
app: error: argument pos_arg: invalid int value: 'foo'

$ ./app 11 2 --opt_arg 3
Argument values:
usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]
convert: error: pos_arg cannot be larger than 10

Full help:

$ ./app -h

usage: app [-h] [--opt_arg OPT_ARG] [--switch] pos_arg [opt_pos_arg]

Optional app description

positional arguments:
  pos_arg            A required integer positional argument
  opt_pos_arg        An optional integer positional argument

optional arguments:
  -h, --help         show this help message and exit
  --opt_arg OPT_ARG  An optional integer argument
  --switch           A boolean switch


Using docopt

Since 2012 Python has a very easy, powerful and really cool module for argument parsing called docopt. It works with Python 2.6 to 3.5 and needs no installation (just copy it). Here is an example taken from it’s documentation:

"""Naval Fate.

  naval_fate.py ship new <name>...
  naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
  naval_fate.py ship shoot <x> <y>
  naval_fate.py mine (set|remove) <x> <y> [--moored | --drifting]
  naval_fate.py (-h | --help)
  naval_fate.py --version

  -h --help     Show this screen.
  --version     Show version.
  --speed=<kn>  Speed in knots [default: 10].
  --moored      Moored (anchored) mine.
  --drifting    Drifting mine.

from docopt import docopt

if __name__ == '__main__':
    arguments = docopt(__doc__, version='Naval Fate 2.0')

So this is it: 2 lines of code plus your doc string which is essential and you get your arguments parsed and available in your arguments object. I told you it’s cool, didn’t I 😉

Using python-fire

Since 2017 python-fire has another cool module which can give a CLI interface to your code with you doing zero argument parsing. Here’s a simple example from the documentation (this small program exposes function double to the command line):

import fire

class Calculator(object):

  def double(self, number):
    return 2 * number

if __name__ == '__main__':

From the command line, you can run:

> calculator.py double 10
> calculator.py double --number=15

Awesome ain’t it?


The new hip way is argparse for these reasons. argparse > optparse > getopt

update: As of py2.7 argparse is part of the standard library and optparse is deprecated.


Pretty much everybody is using getopt

Here is the example code for the doc :

import getopt, sys

def main():
        opts, args = getopt.getopt(sys.argv[1:], "ho:v", ["help", "output="])
    except getopt.GetoptError:
        # print help information and exit:
    output = None
    verbose = False
    for o, a in opts:
        if o == "-v":
            verbose = True
        if o in ("-h", "--help"):
        if o in ("-o", "--output"):
            output = a

So in a word, here is how it works.

You’ve got two types of options. Those who are receiving arguments, and those who are
just like switches.

sys.argv is pretty much your char** argv in C. Like in C you skip the first element which is the name of your program and parse only the arguments : sys.argv[1:]

Getopt.getopt will parse it according to the rule you give in argument.

"ho:v" here describes the short arguments : -ONELETTER. The : means that -o accepts one argument.

Finally ["help", "output="] describes long arguments ( --MORETHANONELETTER ).
The = after output once again means that output accepts one arguments.

The result is a list of couple (option,argument)

If an option doesn’t accept any argument (like --help here) the arg part is an empty string.
You then usually want to loop on this list and test the option name as in the example.

I hope this helped you.


Use optparse which comes with the standard library. For example:

#!/usr/bin/env python
import optparse

def main():
  p = optparse.OptionParser()
  p.add_option('--person', '-p', default="world")
  options, arguments = p.parse_args()
  print 'Hello %s' % options.person

if __name__ == '__main__':

Source: Using Python to create UNIX command line tools

However as of Python 2.7 optparse is deprecated, see: Why use argparse rather than optparse?


Just in case you might need to, this may help if you need to grab unicode arguments on Win32 (2K, XP etc):

from ctypes import *

def wmain(argc, argv):
    print argc
    for i in argv:
        print i
    return 0

def startup():
    size = c_int()
    ptr = windll.shell32.CommandLineToArgvW(windll.kernel32.GetCommandLineW(), byref(size))
    ref = c_wchar_p * size.value
    raw = ref.from_address(ptr)
    args = [arg for arg in raw]
    exit(wmain(len(args), args))


I prefer Click. It abstracts managing options and allows “(…) creating beautiful command line interfaces in a composable way with as little code as necessary”.

Here’s example usage:

import click

@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',
              help='The person to greet.')
def hello(count, name):
    """Simple program that greets NAME for a total of COUNT times."""
    for x in range(count):
        click.echo('Hello %s!' % name)

if __name__ == '__main__':

It also automatically generates nicely formatted help pages:

$ python hello.py --help
Usage: hello.py [OPTIONS]

  Simple program that greets NAME for a total of COUNT times.

  --count INTEGER  Number of greetings.
  --name TEXT      The person to greet.
  --help           Show this message and exit.


I prefer optparse to getopt. It’s very declarative: you tell it the names of the options and the effects they should have (e.g., setting a boolean field), and it hands you back a dictionary populated according to your specifications.



I think the best way for larger projects is optparse, but if you are looking for an easy way, maybe http://werkzeug.pocoo.org/documentation/script is something for you.

from werkzeug import script

# actions go here
def action_foo(name=""):
    """action foo does foo"""

def action_bar(id=0, title="default title"):
    """action bar does bar"""

if __name__ == '__main__':

So basically every function action_* is exposed to the command line and a nice
help message is generated for free.

python foo.py 
usage: foo.py <action> [<options>]
       foo.py --help

    action bar does bar

    --id                          integer   0
    --title                       string    default title

    action foo does foo

    --name                        string


consoleargs deserves to be mentioned here. It is very easy to use. Check it out:

from consoleargs import command

def main(url, name=None):
  :param url: Remote URL 
  :param name: File name
  print """Downloading url '%r' into file '%r'""" % (url, name)

if __name__ == '__main__':

Now in console:

% python demo.py --help
Usage: demo.py URL [OPTIONS]

URL:    Remote URL 

    --name -n   File name

% python demo.py http://www.google.com/
Downloading url ''http://www.google.com/'' into file 'None'

% python demo.py http://www.google.com/ --name=index.html
Downloading url ''http://www.google.com/'' into file ''index.html''


Lightweight command line argument defaults

Although argparse is great and is the right answer for fully documented command line switches and advanced features, you can use function argument defaults to handles straight forward positional arguments very simply.

import sys

def get_args(name='default, first='a', second=2):
    return first, int(second)

first, second = get_args(*sys.argv)
print first, second

The ‘name’ argument captures the script name and is not used. Test output looks like this:

> ./test.py
a 2
> ./test.py A
A 2
> ./test.py A 20
A 20

For simple scripts where I just want some default values, I find this quite sufficient. You might also want to include some type coercion in the return values or command line values will all be strings.


Here’s a method, not a library, which seems to work for me.

The goals here are to be terse, each argument parsed by a single line, the args line up for readability, the code is simple and doesn’t depend on any special modules (only os + sys), warns about missing or unknown arguments gracefully, use a simple for/range() loop, and works across python 2.x and 3.x

Shown are two toggle flags (-d, -v), and two values controlled by arguments (-i xxx and -o xxx).

import os,sys

def HelpAndExit():
    print("<<your help output goes here>>")

def Fatal(msg):
    sys.stderr.write("%s: %s\n" % (os.path.basename(sys.argv[0]), msg))

def NextArg(i):
    '''Return the next command line argument (if there is one)'''
    if ((i+1) >= len(sys.argv)):
        Fatal("'%s' expected an argument" % sys.argv[i])
    return(1, sys.argv[i+1])

### MAIN
if __name__=='__main__':

    verbose = 0
    debug   = 0
    infile  = "infile"
    outfile = "outfile"

    # Parse command line
    skip = 0
    for i in range(1, len(sys.argv)):
        if not skip:
            if   sys.argv[i][:2] == "-d": debug ^= 1
            elif sys.argv[i][:2] == "-v": verbose ^= 1
            elif sys.argv[i][:2] == "-i": (skip,infile)  = NextArg(i)
            elif sys.argv[i][:2] == "-o": (skip,outfile) = NextArg(i)
            elif sys.argv[i][:2] == "-h": HelpAndExit()
            elif sys.argv[i][:1] == "-":  Fatal("'%s' unknown argument" % sys.argv[i])
            else:                         Fatal("'%s' unexpected" % sys.argv[i])
        else: skip = 0

    print("%d,%d,%s,%s" % (debug,verbose,infile,outfile))

The goal of NextArg() is to return the next argument while checking for missing data, and ‘skip’ skips the loop when NextArg() is used, keeping the flag parsing down to one liners.