avatarYang Zhou

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

5987

Abstract

span class="hljs-string">'--verbose'</span>,<span class="hljs-built_in">help</span>=<span class="hljs-string">'Print more info.'</span>) args = parser.parse_args() <span class="hljs-keyword">if</span> args.verbose: <span class="hljs-built_in">print</span>(<span class="hljs-string">f'The square of <span class="hljs-subst">{args.num}</span> is <span class="hljs-subst">{args.num**<span class="hljs-number">2</span>}</span>'</span>) <span class="hljs-keyword">else</span>: <span class="hljs-built_in">print</span>(args.num**<span class="hljs-number">2</span>)</pre></div><p id="ca6f">The above program added an optional argument named <code>--verbose</code>. If there is a value for this argument, the program will print more detailed information for the calculation.</p><p id="798a">Now, let’s try to use it:</p><div id="b48d"><pre><span class="hljs-meta prompt_"></span><span class="language-bash">python test.py 9 --verbose 1</span> The square of 9 is 81 <span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 --verbose 90908</span> The square of 9 is 81 <span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 --verbose</span> usage: get_square [-h] [--verbose VERBOSE] num get_square: error: argument --verbose: expected one argument</pre></div><p id="5426">The annoying issue is that we have to provide a value for this option to make it work, no matter what value it is. If there is no value at all, as illustrated above, an error message will be raised.</p><p id="fe32">This is because the <code>args.verbose</code> is <code>None</code> if we use it directly without assigning any values to it.</p><p id="101c">It’s not as convenient as other Linux commands. So we need to optimise it through <code>action</code> parameters.</p><h1 id="548d">5. Define Special Actions for Optional Arguments</h1><p id="20bc">Let’s change this line of code a bit:</p><div id="87bf"><pre>parser.add_argument(<span class="hljs-string">'--verbose'</span>,<span class="hljs-built_in">help</span>=<span class="hljs-string">'Print more info.'</span>, action=<span class="hljs-string">'store_true'</span>)</pre></div><p id="b3f4">The <code>action</code> parameter of the <code>add_argument()</code> function can give it a guide about how to handle the values of this option.</p><p id="3f3c">In our case, the <code>store_true</code> means if the option is specified, the program will assign the value <code>True</code> to <code>args.verbose</code> by default.</p><p id="2c8d">And then execute the script with the <code>--verbose</code> option directly:</p><div id="ec17"><pre><span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 --verbose</span> The square of 9 is 81</pre></div><p id="09ce">Besides <code>store_true</code> or <code>store_false</code>, Python provides other choices of the <code>action</code> parameters as well. Let’s try a few:</p><h2 id="5ba9">Use the "store_const" action</h2><p id="5d7f">We can use the <code>store_const</code> parameter as an action and assign a <code>const</code> to the optional argument:</p><div id="4ab8"><pre>parser.add_argument(<span class="hljs-string">'--verbose'</span>,<span class="hljs-built_in">help</span>=<span class="hljs-string">'Print more info.'</span>, action=<span class="hljs-string">'store_const'</span>, const=<span class="hljs-number">1</span>)</pre></div><p id="be94">Therefore, the value of the <code>args.verbose</code> will always be 1.</p><h2 id="65a9">Use the “count” action</h2><p id="b021">The <code>'count'</code> parameter counts the number of times an optional argument occurs. Let’s edit our code and try it:</p><div id="a7c3"><pre><span class="hljs-keyword">import</span> argparse parser = argparse.ArgumentParser(prog=<span class="hljs-string">'get_square'</span>,description=<span class="hljs-string">'A CLI to calculate the square of an integer.'</span>) parser.add_argument(<span class="hljs-string">"num"</span>, <span class="hljs-built_in">type</span>=<span class="hljs-built_in">int</span>, <span class="hljs-built_in">help</span>=<span class="hljs-string">'An integer that needs to get the square value.'</span>) parser.add_argument(<span class="hljs-string">'--verbose'</span>,<span class="hljs-built_in">help</span>=<span class="hljs-string">'Print more info.'</span>, action=<span class="hljs-string">'count'</span>) args = parser.parse_args() <span class="hljs-keyword">if</span> args.verbose==<span class="hljs-number">2</span>: <span class="hljs-built_in">print</span>(<span class="hljs-string">f'The square of <span class="hljs-subst">{args.num}</span> is <span class="hljs-subst">{args.num**<span class="hljs-number">2</span>}</span>'</span>) <span class="hljs-keyword">elif</span> args.verbose==<span class="hljs-number">1</span>: <span class="hljs-built_in">print</span>(<span class="hljs-string">f"<span class="hljs-subst">{args.num}</span>^2 == <span class="hljs-subst">{args.num**<span class="hljs-number">2</span>}</span>"</span>) <span class="hljs-keyword">else</span>: <span class="hljs-built_in">print</span>(args.num**<span class="hljs-number">2</span>)</pre></div><p id="3613">In this time, we can determine how detailed the output is through the number of the <code>--verbose</code> options:</p><div id="fac3"><pre><span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 --verbose --verbose</span> The square of 9 is 81 <span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 --verbose</span>
9^2 == 81 <span class="hljs-meta prompt_">$ </span><span class="language-bash">python test.py 9</span>
81</pre></div><h2 id="8e3c">Use the “append” action</h2><p id="498e">The <code>append</code> action stores a list and appends each argument value to a list. In some cases, it will be useful to store multiple values of an optional argument.</p><p id="23eb">To use it, change the following line of the prev

Options

ious Python code:</p><div id="f92e"><pre>parser.add_argument(<span class="hljs-string">'--verbose'</span>,<span class="hljs-built_in">help</span>=<span class="hljs-string">'Print more info.'</span>, action=<span class="hljs-string">'append'</span>)</pre></div><p id="9403">Now, we can add multiple values of the <code>--verbose</code> argument:</p><div id="160c"><pre><span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 --verbose 2 --verbose 3 --verbose 5</span> The verbose values are ['2', '3', '5']. The square of 9 is 81</pre></div><h1 id="b975">6. Define Shortcuts of Optional Arguments</h1><p id="dbc8">It’s a bit boring to input the <code>--verbose</code> many times. Like the <code>-h</code> shortcut for the <code>--help</code> option. We can also define a shortcut for our <code>--verbose</code> option as follows:</p><div id="4fbc"><pre>parser.add_argument(<span class="hljs-string">'-v'</span>,<span class="hljs-string">'--verbose'</span>,<span class="hljs-built_in">help</span>=<span class="hljs-string">'Print more info.'</span>, action=<span class="hljs-string">'count'</span>)</pre></div><p id="d056">After defining the <code>-v</code> shortcut, we can use it directly:</p><div id="a41f"><pre><span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py 9 -vv</span> The square of 9 is 81 <span class="hljs-meta prompt_">$ </span><span class="language-bash">python test.py 9 -v</span> 9^2 == 81</pre></div><h1 id="879d">7. File Handling in Command Line</h1><p id="3908">The <code>argparse</code> module is also able to handle file-type arguments, which makes it convenient to do some basic file operations through command-line interfaces.</p><h2 id="96bc">Read a file through command line</h2><p id="4d94">If we would like to display the content of a file line by line on the terminal, we may write the Python script as follows:</p><div id="1cd4"><pre><span class="hljs-keyword">import</span> argparse

parser = argparse.ArgumentParser() parser.add_argument(<span class="hljs-string">'f'</span>, <span class="hljs-built_in">type</span>=argparse.FileType(<span class="hljs-string">'r'</span>)) args = parser.parse_args()

<span class="hljs-keyword">for</span> line <span class="hljs-keyword">in</span> args.f: <span class="hljs-built_in">print</span>(line.strip())</pre></div><p id="ecf4">Now, let’s execute this Python script on the terminal and pass the <code>test.txt</code> as a file-type argument:</p><div id="facf"><pre><span class="hljs-meta prompt_">$ </span><span class="language-bash">python test.py test.txt</span> Yang is writing a post. Yang is writing on Medium.</pre></div><p id="bc48">As illustrated above, the <code>test.txt</code> file has two lines of sentences. They were printed on the terminal properly with the help of our Python script.</p><h2 id="6618">Write data to a file through command line</h2><p id="244e">To write data to a file, we need to change the operator from <code>r</code> to <code>w</code>:</p><div id="7c10"><pre><span class="hljs-keyword">import</span> argparse

parser = argparse.ArgumentParser() parser.add_argument(<span class="hljs-string">'f'</span>, <span class="hljs-built_in">type</span>=argparse.FileType(<span class="hljs-string">'w'</span>)) args = parser.parse_args()

f = args.f f.write(<span class="hljs-string">'Yang is writing'</span>) f.close()</pre></div><p id="eb8d">The above code will write the sentence “Yang is writing” to the file assigned through a command line interface. The use of it is as follows:</p><div id="4b23"><pre><span class="hljs-meta prompt_"> </span><span class="language-bash">python test.py test.txt</span></pre></div><p id="7e93">After executing the above command, the “test.txt” file will contain one line of the sentence “Yang is writing.”</p><blockquote id="59fb"><p>Tips: Add a shebang to your Python script</p></blockquote><p id="284b">By the way, if you are on Linux or Mac, add a <a href="https://en.wikipedia.org/wiki/Shebang_(Unix)">shebang</a> at the beginning of the Python script will save you from typing <code>python</code> every time:</p><div id="7b86"><pre><span class="hljs-comment">#!/usr/bin/env python3</span></pre></div><p id="7aa0">Now, the Python script can be executed on terminal directly:</p><div id="3bac"><pre> test.py test.txt</pre></div><h1 id="da43">Conclusion</h1><p id="e2af">Mastering the <code>argparse</code> module in Python will help us design and implement easy-to-use command-line interfaces through Python scripts.</p><p id="027b">In the cases that we need a customized CLI but don’t bother to write complex bash scripts, this Python module is our best friend. 👍</p><p id="5ec1"><b><i>Thanks for reading. </i></b>❤️</p><p id="5dc8"><b><i>Enjoy more:</i></b></p><div id="2686" class="link-block"> <a href="https://readmedium.com/9-fabulous-python-tricks-that-make-your-code-more-elegant-bf01a6294908"> <div> <div> <h2>9 Fabulous Python Tricks That Make Your Code More Elegant</h2> <div><h3>Pythonic is a synonym for elegant</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*Jc2HPO7Q4_Jx_AAF3bKaGA.png)"></div> </div> </div> </a> </div><div id="ab4b" class="link-block"> <a href="https://readmedium.com/the-art-of-writing-loops-in-python-68e9869e4ed4"> <div> <div> <h2>The Art of Writing Loops in Python</h2> <div><h3>Simple is better than complex</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*Ew_g2qV84DxA7U1v)"></div> </div> </div> </a> </div></article></body>

7 Levels of Building Command-Line Interfaces in Python

Execute your Python scripts as bash commands

Image from Wallhaven

Writing Python scripts to build command-line interfaces(CLI) is a widely-used technique for DevOps and backend development.

The key to implementing CLI in Python is the built-in argparse module. It provides all necessary functionalities and makes it possible to use a Python script as a bash command.

This article will introduce some essential points of building CLI with Python in 7 levels of complexity.

1. Start a Basic Command-Line Interface with argparse Module

First of all, let’s create a file named test.py and just make a simple argument parser:

import argparse
parser = argparse.ArgumentParser()
parser.parse_args()

Since we defined this parser, we can receive arguments from the command line now. Every ArgumentParser instance contains the --help (or -h as a shortcut) option to print useful information.

$ python test.py --help
usage: test.py [-h]

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

However, because we didn’t define other arguments, the following input will raise an error:

$ python test.py 9     
usage: test.py [-h]
test.py: error: unrecognized arguments: 9

2. Define Positional Arguments

There are two types of arguments in bash commands. One is positional, the other is optional.

For example, the cp command has two positional arguments:

cp source_file dest_file

The source_file specifies the sources of the file to be copied. And the dest_file argument specifies the location to copy the file.

We can define a positional argument for our Python CLI as well:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("num", type=int)
args = parser.parse_args()
print(args.num**2)

As the above code shows, we defined the argument’s name as num and specified its type as int.

Now, as long as the input from terminal is a valid integer, our Python script will print its square:

$ python test.py 9
81

3. Add More Helpful Information and Description

As with many Linux commands, a good CLI should provide enough information to users through its --help option.

For this purpose, we can specify the dedicated information to the corresponding functions of the argparse module.

import argparse
parser = argparse.ArgumentParser(prog='get_square',description='A CLI to calculate the square of an integer.')
parser.add_argument("num", type=int, help='An integer that needs to get the square value.')
args = parser.parse_args()
print(args.num**2)

As demonstrated above, we added the prog and description information into the ArgumentParser instance to give it a name and a detailed description. In addition, we gave the add_argument() function a help message as well to let our users know what this argument is for.

Now, let’s see the output of the -h option again:

$ python test.py -h
usage: get_square [-h] num

A CLI to calculate the square of an integer.

positional arguments:
  num         An integer that needs to get the square value.

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

It’s more user-friendly and informative, isn’t it? 😊

4. Define Optional Arguments

Besides the positional arguments, optional arguments are also necessary for many command-line interfaces.

The built-in --help option of all ArgumentParser instances is an optional argument. We can add another one to the previous example:

import argparse
parser = argparse.ArgumentParser(prog='get_square',description='A CLI to calculate the square of an integer.')
parser.add_argument("num", type=int, help='An integer that needs to get the square value.')
parser.add_argument('--verbose',help='Print more info.')
args = parser.parse_args()
if args.verbose:
    print(f'The square of {args.num} is {args.num**2}')
else:
    print(args.num**2)

The above program added an optional argument named --verbose. If there is a value for this argument, the program will print more detailed information for the calculation.

Now, let’s try to use it:

$ python test.py 9 --verbose 1
The square of 9 is 81

$ python test.py 9 --verbose 90908
The square of 9 is 81

$ python test.py 9 --verbose
usage: get_square [-h] [--verbose VERBOSE] num
get_square: error: argument --verbose: expected one argument

The annoying issue is that we have to provide a value for this option to make it work, no matter what value it is. If there is no value at all, as illustrated above, an error message will be raised.

This is because the args.verbose is None if we use it directly without assigning any values to it.

It’s not as convenient as other Linux commands. So we need to optimise it through action parameters.

5. Define Special Actions for Optional Arguments

Let’s change this line of code a bit:

parser.add_argument('--verbose',help='Print more info.', action='store_true')

The action parameter of the add_argument() function can give it a guide about how to handle the values of this option.

In our case, the store_true means if the option is specified, the program will assign the value True to args.verbose by default.

And then execute the script with the --verbose option directly:

$ python test.py 9 --verbose
The square of 9 is 81

Besides store_true or store_false, Python provides other choices of the action parameters as well. Let’s try a few:

Use the "store_const" action

We can use the store_const parameter as an action and assign a const to the optional argument:

parser.add_argument('--verbose',help='Print more info.', action='store_const', const=1)

Therefore, the value of the args.verbose will always be 1.

Use the “count” action

The 'count' parameter counts the number of times an optional argument occurs. Let’s edit our code and try it:

import argparse
parser = argparse.ArgumentParser(prog='get_square',description='A CLI to calculate the square of an integer.')
parser.add_argument("num", type=int, help='An integer that needs to get the square value.')
parser.add_argument('--verbose',help='Print more info.', action='count')
args = parser.parse_args()
if args.verbose==2:
    print(f'The square of {args.num} is {args.num**2}')
elif args.verbose==1:
    print(f"{args.num}^2 == {args.num**2}")
else:
    print(args.num**2)

In this time, we can determine how detailed the output is through the number of the --verbose options:

$ python test.py  9 --verbose --verbose
The square of 9 is 81
$ python test.py  9 --verbose          
9^2 == 81
$ python test.py  9          
81

Use the “append” action

The append action stores a list and appends each argument value to a list. In some cases, it will be useful to store multiple values of an optional argument.

To use it, change the following line of the previous Python code:

parser.add_argument('--verbose',help='Print more info.', action='append')

Now, we can add multiple values of the --verbose argument:

$ python test.py  9 --verbose 2 --verbose 3 --verbose 5
The verbose values are ['2', '3', '5'].
The square of 9 is 81

6. Define Shortcuts of Optional Arguments

It’s a bit boring to input the --verbose many times. Like the -h shortcut for the --help option. We can also define a shortcut for our --verbose option as follows:

parser.add_argument('-v','--verbose',help='Print more info.', action='count')

After defining the -v shortcut, we can use it directly:

$ python test.py  9 -vv
The square of 9 is 81
$ python test.py  9 -v
9^2 == 81

7. File Handling in Command Line

The argparse module is also able to handle file-type arguments, which makes it convenient to do some basic file operations through command-line interfaces.

Read a file through command line

If we would like to display the content of a file line by line on the terminal, we may write the Python script as follows:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('f', type=argparse.FileType('r'))
args = parser.parse_args()

for line in args.f:
    print(line.strip())

Now, let’s execute this Python script on the terminal and pass the test.txt as a file-type argument:

$ python test.py test.txt
Yang is writing a post.
Yang is writing on Medium.

As illustrated above, the test.txt file has two lines of sentences. They were printed on the terminal properly with the help of our Python script.

Write data to a file through command line

To write data to a file, we need to change the operator from r to w:

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('f', type=argparse.FileType('w'))
args = parser.parse_args()

f = args.f
f.write('Yang is writing')
f.close()

The above code will write the sentence “Yang is writing” to the file assigned through a command line interface. The use of it is as follows:

$ python test.py test.txt

After executing the above command, the “test.txt” file will contain one line of the sentence “Yang is writing.”

Tips: Add a shebang to your Python script

By the way, if you are on Linux or Mac, add a shebang at the beginning of the Python script will save you from typing python every time:

#!/usr/bin/env python3

Now, the Python script can be executed on terminal directly:

$ test.py test.txt

Conclusion

Mastering the argparse module in Python will help us design and implement easy-to-use command-line interfaces through Python scripts.

In the cases that we need a customized CLI but don’t bother to write complex bash scripts, this Python module is our best friend. 👍

Thanks for reading. ❤️

Enjoy more:

Programming
Python
Technology
Data Science
DevOps
Recommended from ReadMedium