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
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
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 argumentssys.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 theadd_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 theArgumentParser
object.
Next, learn how to perform secure hashing in Python.