Want to run Python scripts with command-line arguments? Learn how to parse command-line arguments using sys, getopt, and argparse modules in Python.

In Python, when you want to read in user input, you’ll use the input() function. However, for some applications, you may want to pass in certain arguments while running the script at the command line.

In this tutorial, we’ll learn how to run a Python script with options and arguments at the command line. We’ll then learn how to use Python’s built-in modules to parse such options and arguments.

Let’s begin!

Understanding sys.argv in Python

If you have programmed in C, you know that one of the simplest ways to pass in arguments to the program is via the command line. To do so, you can structure the main function like so:

#include<stdio.h>

int main(int argc, char **argv){
    //argc: argument count
    //argv: argument vector
    
    //do something on the args

    return 0;
}

Here, argc stands for argument count and argv stands for argument vector.

Running Python Scripts with Command-Line Arguments

In Python, you can run the Python script at the command line using python3 filename.py. When doing so, you can also pass in an arbitrary number of command-line arguments:

$ python3 filename.py arg1 arg2 ... argn

The sys module provides out-of-the-box support to access and process these command-line arguments. sys.argv is the list of all the command-line arguments that we pass in when we run the Python script.

Here’s an example where we run main.py with command-line arguments:

$ python3 main.py hello world python script

We can loop through the argument vector using a simple for loop and enumerate function:

# main.py

import sys

for idx, arg in enumerate(sys.argv):
    print(f"arg{idx}: {arg}")
# Output
arg0:main.py
arg1:hello
arg2:world
arg3:python
arg4:script

We see that the first argument (at index 0) is the name of the Python file. And subsequent arguments start at index 1.

This is a minimal working program that accepts and processes command-line arguments. However, we see some issues:

  • How do users of the program know what arguments to pass in?
  • And what do these arguments stand for?

This is not very clear. To address this, you can use either the getopt or the argparse modules. And we’ll learn that in the next sections.✅

Command-Line Argument Parsing Using Python’s getopt

python-command-line-arguments-1

Let’s learn how to parse command-line arguments using the built-in getopt module.

After importing getopt from the getopt module, you can specify the arguments to parse and the short options and long options to run the script with. We need to parse all arguments starting at index 1 in sys.argv. So the slice to parse is sys.argv[1:].

Here, we’ll need a message string and file name. Let’s use m and f as short options and message and file as long options.

But how do we ensure that a specific option requires an argument? 

  • In short options, you can make an option require an argument by adding a colon (:) after the short option name.
  • Similarly, in long options, you can add an = sign after the long option. We can capture these options and their respective arguments.

Adding these in, we’ll have the following code in main.py:

# main.py

import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=','file='])

print(opts)
print(args)

Here, the variable opts contains the options and arguments as a list of tuples. Any other positional argument that we pass in will be collected in args variable.

We can pass in the message and the filename to run the script, and we can use either the short options or the long options.

Running main.py using the long options, we have:

$ python3 main.py --message hello --file somefile.txt

We have the options and arguments as tuples in the opts variable. As we haven’t passed in any positional argument, args is an empty list.

# Output
[('--message', 'hello'), ('--file', 'somefile.txt')]
[]

Equivalently, we can also use the short options as shown:

$ python3 main.py -m hello -f somefile.txt
# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
[]

⚠️ The -m short option in this example is not to be confused with the command-line flag -m which is used to run a module as the main module when running a Python script.

For example, you’ll use python3 -m unittest main.py to run unittest as the main module when running main.py.

We mentioned that all other positional arguments that we pass in will be collected in the args variable. Here’s an example:

$ python3 main.py -m hello -f somefile.txt another_argument

The args list contains the positional argument another_argument.

# Output
[('-m', 'hello'), ('-f', 'somefile.txt')]
['another_argument']

Here, opts is a list of tuples. So we can loop through it, unpack the tuple, and pull out the arguments corresponding to the specific options.

But what do we do with the filename and the message after we have processed these arguments? We’ll open the file in the write mode and write the message string converted to uppercase to the file.

# main.py
import sys
from getopt import getopt

opts, args = getopt(sys.argv[1:],'m:f:',['message=','file='])

print(opts)
print(args)

for option, argument in opts:
    if option == '-m':
        message = argument
    if option == '-f':
        file = argument

with open(file,'w') as f:
    f.write(message.upper())

Let’s run main.py with the short options and command-line arguments.

$ python main.py -m hello -f thisfile.txt
[('-m', 'hello'), ('-f', 'thisfile.txt')]
[]

After running main.py, we can see ‘thisfile.txt’ in our working directory. It contains the string ‘hello’ converted to uppercase (‘HELLO’).

$ ls
main.py  thisfile.txt
$ cat thisfile.txt
HELLO

How to Parse Command-Line Arguments with Argparse

python-command-line-arguments-2

The argparse module, also built into the Python standard library, provides functionality to parse command-line arguments and also build command-line interfaces.

To parse command-line arguments, let us import the ArgumentParser class from the argparse module. Here, we’ve instantiated arg_parser, an ArgumentParser object:

from argparse import ArgumentParser

arg_parser = ArgumentParser()

Next, we’d like to add two command-line arguments:

  • message: the message string, and 
  • file: the name of the file we’d like to work with.

Now we call the add_argument() method on arg_parser to add both these arguments. In the add_argument() method call, you can set help to a string (a description of the argument).

arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

So far, we’ve instantiated arg_parser and added the command-line arguments. When the program is run at the command line, you can use the parse_args() method on arg_parser to get the values of the arguments.

Here, we capture the argument namespace in the variable args. So you can use args.argument_name to get the values of the arguments.

After getting the values of the arguments, we write the message string with case swapped (using the swapcase() string method) to the file.

args = arg_parser.parse_args()

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Putting it all together, here’s our main.py file:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('message',help='message string')
arg_parser.add_argument('file',help='filename')

args = arg_parser.parse_args()
print(args)

message = args.message
file = args.file

with open(file,'w') as f:
     f.write(message.swapcase())

Understanding Command-Line Argument Usage

To understand the usage of the arguments when running main.py, you can use the --help long option as shown:

$ python3 main.py --help
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

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

There are no optional arguments and both message and file are required positional arguments. Alternatively, you can also use short option -h:

$ python3 main.py -h
usage: main.py [-h] message file

positional arguments:
  message     message string
  file        filename

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

As seen, both the arguments are positional arguments by default. So if you do not pass in one or more of these arguments, you’ll run into errors.

Here, we’ve passed in a positional argument (Hello) for the message string, but we have not supplied any value for the file argument.

And we get an error stating that the file argument is required.

$ python3 main.py Hello
usage: main.py [-h] message file
main.py: error: the following arguments are required: file

When we run main.py with both the positional arguments, we see that the namespace args contains the values of the arguments.

$ python3 main.py Hello file1.txt
# Output
Namespace(file='file1.txt', message='Hello')

Now if we examine the contents of the present working directory, we see that the script creates the file ‘file1.txt’:

$ ls
file1.txt  main.py

The original message string is ‘Hello’; after swapping the case the message string in the file ‘file1.txt’ is ‘hELLO’.

$ cat file1.txt
hELLO

How to Make Command-Line Arguments Optional

To make these command-line arguments optional, you can prefix the argument name with --.

Let’s modify main.py to make both the message and the file arguments optional.

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

As the command-line arguments are both optional, we can set default values for these arguments.

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message = 'Python3'
    file = 'myfile.txt'

At this point, the main.py file contains the following code:

# main.py

from argparse import ArgumentParser

arg_parser = ArgumentParser()
arg_parser.add_argument('--message',help='message string')
arg_parser.add_argument('--file',help='filename')

args = arg_parser.parse_args()
print(args)

if args.message and args.file:
    message = args.message
    file = args.file
else:
    message = 'Python3'
    file = 'myfile.txt'

with open(file,'w') as f:
     f.write(message.swapcase())

If we check the usage, we see that both message and file are optional arguments. Meaning you can now run main.py without both of these arguments.

$ python3 main.py --help
usage: main.py [-h] [--message MESSAGE] [--file FILE]

optional arguments:
  -h, --help         show this help message and exit
  --message MESSAGE  message string
  --file FILE        filename
$ python3 main.py

In the argument namespace, both file and message are None.

# Output
Namespace(file=None, message=None)

We see that the default file name and message ‘myfile.txt’ and ‘Python3’ are used. The file ‘myfile.txt’ is now in the working directory:

$ ls
file1.txt  main.py  myfile.txt

And it contains the string ‘Python3’ with the case of the letters swapped:

$ cat myfile.txt
pYTHON3

You can also use both the --message and the --file arguments to make the command more readable.

$ python3 main.py --message Coding --file file2.txt
# Output
Namespace(file='file2.txt', message='Coding')

We see the ‘file2.txt’ in the working directory:

$ ls
file1.txt  file2.txt  main.py  myfile.txt

And it contains the string ‘cODING’ as expected.

$ cat file2.txt
cODING

Conclusion

Here’s a summary of what we’ve learned in this tutorial:

  • Similar to the C programming language, in Python, you can access the command-line arguments by looping through the argument vector sys.argv. sys.argv[0] is the name of the Python script. So we’re interested in parsing the arguments sys.argv[1:].
  • However to enhance readability and to be able to add options, you can use to getopt and argparse modules.
  • You can use the getopt module to parse the list of command-line arguments starting at index 1 up to the end of the list. You can specify both short opts and long opts.
  • When an option takes an argument, you can specify a colon (:) and = after the short option and long option, respectively.
  • With Python’s argparse module, you can instantiate an ArgumentParser object and use the add_argument() method to add a required positional argument. Use -- before the argument name to make it optional. 
  • To retrieve the values of the command-line arguments, call the parse_args() method on the ArgumentParser object.

Next, learn how to perform secure hashing in Python.