Creating CLI Commands using Argparse in Python
Sachin
Posted on March 31, 2024
Python has a rich and versatile collection of standard libraries, making it one of the better programming languages, so it needs to cover all the areas of programming.
If developers want to write the scripts for the command line using Python, then there must be some libraries that allow them to write command line scripts conveniently. Python has a library called argparse
that helps to create exemplary command-line interfaces for the command-line scripts.
In this article, we'll be going to learn:
What is
argparse
in PythonHow to create a basic CLI in Python using
argparse
What are the advanced features of Python
argparse
What is CLI
A command line interface, short for CLI, is a medium or type of interface that allows us to interact with a command line script. Python has many libraries that allow us to write the command line interface for our scripts. We'll use a library called argparse
to create a CLI in Python.
It is a standard way to create a CLI in Python, and argparse
came as a replacement for the modules like optparse and getopt because they lacked some significant features.
Getting to know CLI
Before we proceed any further, we need to know how the command line interface works, so open up your terminal on your computer and execute a command 'python' to start using Python commands in your command line.
>python
....
Python 3.10.5 (tags/v3.10.5:f377153, Jun 6 2022, 16:14:13) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print("Hello Geeks!")
Hello Geeks!
>>> 3 % 6
3
>>> sum([4, 19, 111])
134
Here we can execute the Python commands directly in our CLI. Fortunately, we don't need any Python interpreter to get started. Still, we can add an option(type of argument) with the argument to get the extra information.
>python --version
....
Python 3.10.5
>python -q
....
>>> print("Python has started without prompting copyright and version messages.")
Python has started without prompting copyright and version messages.
Here we obtained the version of Python that we are currently using by just adding the --version
option to the python
argument, and in the second command, we used the -q
option to start the Python interpreter without prompting the version and copyright messages that it usually shows on startup.
To understand arguments, options, and parameters, consider the following example:
>dir /d /r D:\SACHIN\Pycharm\cli_flask
dir: The name of the command we are executing
/d: An option to display all directories in the current path
/r: An option to display the read-only files
D:\SACHIN\Pycharm\cli_flask: A parameter to list the directories in the specified path
To explain precisely,
An argument is a command that we want to execute.
An option is a part of an argument or type of argument used to modify the behavior of the command line.
A parameter is a type of argument that provides additional information to the command.
Creating a basic command using argparse
We can create an essential command for CLI in a few steps using argparse
. Let's understand the measures included in the process of making the command.
Importing the
argparse
because it's a Python libraryCreating the parser
Adding the positional and optional arguments to the parser
Executing the parser using the
parse_args()
Let's assume we have a file named command.py
in which we write the basic command to get the factorial of the integer specified in the command line interface or CLI.
# Importing argparse library
import argparse
from math import factorial
# Creating the parser
parser = argparse.ArgumentParser(description='Get the factorial of the integer.')
# Adding the argument
parser.add_argument('Factorial',
metavar='integer',
type=int,
help='factorial of the integer')
# Executing the parser using parse_args() method
args = parser.parse_args()
fact = args.Factorial
print(factorial(fact))
We've coded our first-ever command for CLI and now let's understand our code. We can divide our code into four parts.
First, we imported the argparse
library and then created the parser using the ArgumentParser()
method in which we passed the detail
argument to specify the detail of our command.
Next, we added the argument to the parser using the add_argument
method, which holds the necessary information passed into the arguments inside the method. Finally, we executed our parser using the parse_args()
method.
If we run our command in the CLI without specifying any value, then we will get an error and a usage message.
>python command.py
usage: command.py [-h] integer
command.py: error: the following arguments are required: integer
The program detected that we needed a positional argument (integer
) to complete the execution, but the execution was interrupted due to the absence of the positional argument.
We can see that our command accepts an optional -h
flag.
>python command.py -h
usage: command.py [-h] integer
Get the factorial of the integer.
positional arguments:
integer factorial of the integer
options:
-h, --help show this help message and exit
If we execute our command with the positional argument it needs, we'll get the desired result.
>python command.py 6
720
Advanced usage of argparse
We learned the basic usage of the argparse
library, and now we can create an essential command for CLI. However, this is not it, we can do many more things using this library. We'll see some advanced usage of the argparse
library.
Display custom help message
The argparse
library generates usage help if not provided, but we can customize the help message using the usage
keyword.
parser = argparse.ArgumentParser(
usage='command.py [options] integer',
description='Get the factorial of the integer.')
Now we can see the different usage messages if we execute the program.
>python command.py
usage: factorial [options] integer
factorial: error: the following arguments are required: integer
Setting the program name
In the previous section, we saw the Python script name when we executed the program in the CLI because the library uses the sys.argv[0]
to set the program's name. However, we can specify the program name using the prog
keyword.
parser = argparse.ArgumentParser(
prog='factorial',
description='Get the factorial of the integer.')
We will now see our specified name, factorial
, of the program in the CLI instead of the Python script name.
>python command.py
usage: factorial [-h] integer
factorial: error: the following arguments are required: integer
Displaying text before and after the arguments
We can customize the text we want to display before and after in the help text by using the following keywords.
description: for the text shown before the help text
epilog: for the text shown after the help text
We have already seen the use of description
. This time we'll use the epilog
to display the text after the help text.
parser = argparse.ArgumentParser(
description='Get the factorial of the integer.',
epilog='Have you understood the process? ')
We will see the customized message after the help text.
>python command.py -h
usage: command.py [-h] integer
Get the factorial of the integer.
positional arguments:
integer factorial of the integer
options:
-h, --help show this help message and exit
Have you understood the process?
Customizing prefix character
The optional arguments in the CLI command are generally prefixed with (-
), a standard prefix char. The argparse
library has a feature that allows us to customize the prefix chars.
The prefix_chars
keyword lets us customize the prefix character while defining the parser.
parser = argparse.ArgumentParser(
description='Get the factorial of the integer.',
prefix_chars='$')
Now, in the output, we won't see (-
) as the prefix char for the optional argument instead, we will see the ($
) as the prefix char.
>python command.py
usage: command.py [$h] integer
command.py: error: the following arguments are required: integer
Now our program does not support the -h
flag but the $h
flag. The help text has also changed accordingly.
Enable and disable help
Python argparse
library automatically generates the help text without having to code anything. However, sometimes we wanted to disable the feature. We can add the add_help
keyword when creating the parser.
parser = argparse.ArgumentParser(
description='Get the factorial of the integer.',
add_help=False)
We've added the add_help
keyword in the above code and set its value to False
. It ensures that the program does not accept the -h
flag anymore.
>python command.py
usage: command.py integer
command.py: error: the following arguments are required: integer
Allowing and disallowing abbreviation
One of the features the Python argparse
library provides is the ability to handle abbreviations. Consider the following example that prints the square of the specified integer.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--square', action='store', type=int)
parser.add_argument('--sum', action='store', type=int)
args = parser.parse_args()
print(args.square**2)
We can shorten the optional argument until the abbreviation leads to the wrong interpretation.
>python abbreviation.py --square 4
16
>python abbreviation.py --squar 4
16
>python abbreviation.py --squa 4
16
>python abbreviation.py --squ 4
16
>python abbreviation.py --sq 4
16
We can shorten the optional argument until --sq 4
. What happens if we execute the program specifying --s 4
? It might lead to an error because argparse
doesn't know whether we want to specify 4 to the --square
or the --sum
argument.
>python abbreviation.py --s 4
usage: abbreviation.py [-h] [--square SQUARE] [--sum SUM]
abbreviation.py: error: ambiguous option: --s could match --square, --sum
However, we can force users to specify the full name of the option by disabling the feature by adding the allow_abbrev
while creating the parser.
import argparse
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument('--square', action='store', type=int)
parser.add_argument('--sum', action='store', type=int)
args = parser.parse_args()
print(args.square**2)
Now, if we try to execute the program using an abbreviation, the program will throw an error.
>python abbreviation.py --squa 4
usage: abbreviation.py [-h] [--square SQUARE]
abbreviation.py: error: unrecognized arguments: --squa 4
Setting the name or flag of the arguments
There are two types of arguments that we can use in our command line interface:
Positional arguments
In the previous examples, we've already seen the positional arguments. In the example above, Factorial
was the positional argument, and our program couldn't work without it.
Positional arguments are the types of argument that we use in command to perform some operation. They are called positional arguments because their position defines their function.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('Square', type=int, help='square of the integer')
args = parser.parse_args()
print(args.Square**2)
Here, Square
is the positional argument, and when we specify an integer, the program returns the square of that integer. By default, the positional argument is treated as a String, so we used the type
keyword and set its value to int
to typecast the string into the integer.
Optional arguments
The optional arguments are used to perform the additional tasks, and when they are used, they can modify the command's behavior at runtime.
For example, if we look at the ls
command that lists the files in a current directory and if we use the -l
argument, which is an optional argument, it modifies the output and returns the extra information.
$ ls -l
Optional arguments are not mandatory, and we won't get any errors if we don't specify them. They are generally prefixed with a (-
) dash or (--
) double dash.
import argparse
import math
parser = argparse.ArgumentParser()
parser.add_argument('-s',
'--sq_root',
type=int,
help='square root of the integer')
args = parser.parse_args()
sqrt = args.sq_root
print(math.sqrt(sqrt))
Output
>python op_arg.py --sq_root 9
3.0
>python op_arg.py -s 9
3.0
Setting the action
When we add an argument to the command line interface, we can also define the kind of action to take when the argument is specified.
The action
keyword argument specifies how the command-line arguments should be handled. Many actions are available and ready to use:
store: stores the argument's value. This is the default action.
store_const: stores a constant value when the optional arguments are specified.
store_true and store_false: used for storing the boolean values
True
andFalse
respectively when the optional arguments are specified and stores a False and True elsewhere, respectively.append: stores a list and appends each argument value to the list.
append_const: stores a list and appends the constant value to the list each time the option is provided.
count: counts the number of times the option is provided.
help: shows the help message and then exits.
version: shows the program's version information and exits.
extend: stores a list and extends each argument value to the list. It was added in Python v3.8.
Let's understand what these actions can do with simple examples.
We've used the action='store'
in the following example, which will store the specified value.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--store', action='store')
args = parser.parse_args()
print(args.store)
print(vars(args))
Output
>python action.py --store 23
23
{'store': '23'}
>python action.py --store hello
hello
{'store': 'hello'}
The action='store_const'
stores the value specified by the const keyword. We've defined the const
keyword and set its value to hello
.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--sc', action='store_const', const='hello')
args = parser.parse_args()
print(vars(args))
We just provided the --sc
argument, and we got the value specified in the const
keyword because the value of args.sc
is now hello
.
>python action.py --sc
{'sc': 'hello'}
The action='store_true'
stores the boolean True
and stores the False
elsewhere when the arguments are passed. We can use action='store_false'
for the opposite behavior.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--st', action='store_true')
args = parser.parse_args()
print(vars(args))
Output
>python action.py
{'st': False}
>python action.py --st
{'st': True}
The action='append'
creates a list of values passed in the CLI.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--append', action='append')
args = parser.parse_args()
print(vars(args))
Output
>python action.py --append hello --append world
{'append': ['hello', 'world']}
The action='append_const'
is the same as append
, but it appends the same constant value.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--ac', action='append_const', const='2')
args = parser.parse_args()
print(vars(args))
Output
>python action.py --ac --ac --ac
{'ac': ['2', '2', '2']}
The action='count'
counts the number of times the argument is passed.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--count', action='count', default=0)
args = parser.parse_args()
print(vars(args))
Output
>python action.py --count --count --count --count
{'count': 4}
We've already seen the help message in our examples previously, which is enabled for the -h
flag. The action='help'
lets us use another flag for the help message.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-x', action='help')
args = parser.parse_args()
print(vars(args))
Output
>python action.py -x
usage: action.py [-h] [-x]
options:
-h, --help show this help message and exit
-x
The action='version'
helps us to get the program's version, but it expects a version
keyword.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-z', action='version', version='1.11')
args = parser.parse_args()
print(vars(args))
Output
>python action.py -z
1.11
The action='extend'
extends the argument values to the list.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-e', action='extend', nargs='+')
args = parser.parse_args()
print(vars(args))
Output
>python action.py -e 2 4 6 3 -e 0 9
{'e': ['2', '4', '6', '3', '0', '9']}
Setting the default value
Since the optional arguments are not mandatory, they can be omitted by the user in the command line interface. In this situation, the value is generally set to None
.
We can set the default value for an argument when it is not provided using the default
keyword.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', default=5)
args = parser.parse_args()
print(vars(args))
We'll get the following output if we execute the program without specifying the -d
option.
>python default.py
{'d': 5}
We didn't receive any error because option -d
is set to 5.
Setting the type of the argument
By default, the input arguments are treated as a string, and we can typecast the input arguments in the desired datatype using the type
keyword. We've already seen examples where we used the type
keyword.
import argparse
import math
parser = argparse.ArgumentParser()
parser.add_argument('-f', type=int,)
args = parser.parse_args()
print(math.factorial(args.f))
type=int
will ensure that the argument's value must be an integer instead of a string.
>python type.py -f 2
2
The value of the argument is checked at the runtime. If there is any datatype other than the integer provided in the command line, then the program will throw an error.
>python type.py -f a
usage: type.py [-h] [-f F]
type.py: error: argument -f: invalid int value: 'a'
The error clearly states that the value a
is an invalid integer, and we need to pass an integer instead of a string.
Making the argument to be required
The user can omit the optional arguments. However, we can force the user to specify the value for an optional argument by making the argument to be required by using the required
keyword.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-d', required=True)
args = parser.parse_args()
print(vars(args))
We used the required
keyword and set its value to True
, which forces the user to specify the value for the argument.
>python required.py
usage: required.py [-h] -d D
required.py: error: the following arguments are required: -d
Note: It is a bad practice to make an optional argument to be required by the user because the name itself depicts that it is optional, and the user wouldn't expect to set a value for the argument.
Setting the number of values the argument can take
Usually, we specify the single value to the argument, which is the default behavior. We can change this default behavior by specifying the number of values an argument can consume using the nargs
keyword.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--value', type=int, nargs=2)
args = parser.parse_args()
print(args.value)
The program will accept only two values, not more or less than that.
>python nargs.py --value 1
usage: nargs.py [-h] [--value VALUE VALUE]
nargs.py: error: argument --value: expected 2 arguments
>python nargs.py --value 1 2
[1, 2]
>python nargs.py --value 1 2 34
usage: nargs.py [-h] [--value VALUE VALUE]
nargs.py: error: unrecognized arguments: 34
As we can see, when we provided a single and more than two values, the program threw an error, but when we provided the two values, the program returned the list containing the two values.
Instead of using any integer, the nargs
keyword also accepts the following:
?: a single value will be consumed, which can be optional
*: an extensible number of values, which will be gathered into a list
+: much like *, but it requires at least one value
argparse.REMAINDER: all the values that are remaining in the command line
In the following example, the positional argument value
accepts a single value. If the value is not provided, it returns the value set in the default
keyword.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('value',
nargs='?',
default='This is a default value.')
args = parser.parse_args()
print(args.value)
We can now set the specific value for the value
argument. If the value is not provided, it will prompt the default value in the command line.
>python nargs.py 2
2
>python nargs.py
This is a default value.
If we wanted to provide a flexible number of values and gather them into a list, then we need to use the ***** value for the nargs
keyword.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('value',
nargs='*',
default='This is a default value.')
args = parser.parse_args()
print(args.value)
The above code allows us to set a flexible number of values, which we can see in the following output.
>python nargs.py more than one value
['more', 'than', 'one', 'value']
>python nargs.py
This is a default value.
We can use the + value for the nargs
keyword when we want a variable number of values, but we need to ensure that at least one value is specified.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('value',
nargs='+',)
args = parser.parse_args()
print(args.value)
The above code can accept a variable number of values but make sure at least one value is specified. Otherwise, it will throw an error.
>python nargs.py needs at least one value
['needs', 'at', 'least', 'one', 'value']
>python nargs.py
usage: nargs.py [-h] value [value ...]
nargs.py: error: the following arguments are required: value
As we can see, when we executed the program without any value, it threw an error, while when we provided multiple values, it returned the list containing the values.
Consider the following example, where we're using the argparse.REMAINDER
value to the nargs
for the remaining
argument to grab all the remaining values that have been specified in the command line and put them in a list.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('value')
parser.add_argument('remaining', nargs=argparse.REMAINDER)
args = parser.parse_args()
print(f'First value: {args.value}')
print(f'Other values: {args.remaining}')
If we execute the program, the first value will be assigned to the first argument, and the remaining will be assigned to the second argument.
>python nargs.py hey there geeks
First value: hey
Other values: ['there', 'geeks']
Displaying an alternate name for the argument
Using the metavar
keyword, we can set the name for our argument that will show in the usage message.
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-s',
'--square',
metavar='Square',)
args = parser.parse_args()
print(vars(args))
If we execute the program with the -h
flag, we can see the name Square will be assigned to the -s
and --square
options in the help text.
>python metavar.py -h
usage: metavar.py [-h] [-s Square]
options:
-h, --help show this help message and exit
-s Square, --square Square
Conclusion
This tutorial is a bit lengthy, but it is meant to be because it has detailed information about the argparse
library in Python, allowing us to build the command-line interface.
We've covered the basic and advanced usage of the argparse
with simple examples. We are now able to build our command-line interface conveniently.
Let's review what we've learned:
what is Python
argparse
library and how to use itcreated the basic command-line interface
what are the advanced usage of the Python
argparse
library
πOther articles you might be interested in if you liked this one
β Split your string into an array of words using the split() method in Python.
β Map a function to each item in an iterable using the map() function.
β Serialize and deserialize Python objects using the pickle module.
β Why if __name__ == β__main__β is used in Python programs?
β Create a WebSocket server and client in Python.
β Upload and display images on the frontend using Flask.
That's all for now
Keep Codingββ
Posted on March 31, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.