Adventures in Machine Learning

Building CLI Applications with Python: An Introduction

Command-line applications (CLI) have been around since the early days of computing. They are powerful tools for executing complex tasks and tasks that need to be done repeatedly without user intervention.

CLI tools are essential for developers and system administrators as they provide efficient ways to interact with computer systems. Thanks to some excellent tools like argparse, click, and docopt, developing CLI applications has never been easier.

In this article, we’ll get into the basics of CLI application development and learn how to build our first CLI applications. Basic Usage:

Running basic commands:

The first step in building any CLI application is to create and run basic commands.

We can use any programming language to build CLI applications, but for simplicity and ease of use, we’ll use Python in this article. Python is a popular programming language that has excellent libraries for building CLI applications.

To run a basic command, we’ll create a new Python file and add the following code:

“`

#!/usr/bin/env python

print(“Hello, World!”)

“`

Save the file as `hello.py`. Open the terminal, navigate to the directory of the `hello.py` file, and type `./hello.py`.

You’ll see the output “Hello, World!” printed in the terminal. Adding command-line arguments:

Often, we need to pass arguments to our CLI applications.

To do this, we need to use Python’s `sys.argv` list, which contains the command-line arguments passed to our application. Let’s modify our `hello.py` file to accept a name argument.

“`

#!/usr/bin/env python

import sys

name = sys.argv[1]

print(f”Hello, {name}!”)

“`

Save the file as `hello.py`. Open the terminal, navigate to the directory of the `hello.py` file, and type `./hello.py John`.

You’ll see the output “Hello, John!” printed in the terminal. Adding options/flags:

Options and flags are additional arguments that can be passed to our CLI applications.

Options are arguments that require a value, while flags are arguments that toggle a Boolean value. We can use libraries like argparse, click, and docopt to make it easier to add these options and flags to our application.

Let’s modify our `hello.py` file to accept an optional `–upper` flag. Using argparse:

“`

#!/usr/bin/env python

import argparse

parser = argparse.ArgumentParser()

parser.add_argument(“name”, help=”The name of the person.”)

parser.add_argument(“–upper”, help=”Convert name to uppercase.”, action=”store_true”)

args = parser.parse_args()

if args.upper:

name = args.name.upper()

else:

name = args.name

print(f”Hello, {name}!”)

“`

Using click:

“`

#!/usr/bin/env python

import click

@click.command()

@click.argument(“name”)

@click.option(“–upper”, is_flag=True, help=”Convert name to uppercase.”)

def hello(name, upper):

if upper:

name = name.upper()

click.echo(f”Hello, {name}!”)

if __name__ == “__main__”:

hello()

“`

Using docopt:

“`

#!/usr/bin/env python

“””Usage: hello.py [options] NAME

Options:

-u, –upper Convert name to uppercase. “””

from docopt import docopt

args = docopt(__doc__)

name = args[“NAME”]

if args[“–upper”]:

name = name.upper()

print(f”Hello, {name}!”)

“`

All three libraries function similarly. They create a parser, add arguments, parse the arguments, and run the appropriate functions based on the arguments passed.

Conclusion:

In conclusion, CLI applications are an essential tool for developers and system administrators. They provide an efficient way of interacting with computer systems.

Python is a popular language that makes it easy to build these applications, thanks to libraries like argparse, click, and docopt. We learned how to create and run basic CLI commands and how to add command-line arguments, options, and flags.

In the end, we saw how to use argparse, click, and docopt libraries to add these features. Knowing how to build CLI applications is an essential skill that every developer must have.

Task-runner libraries and command-line interfaces:

CLI applications can be used for more than just running simple commands. They can also be used to automate complex tasks with ease.

A task-runner library like Invoke can be used to create and run tasks from the command line. Invoke is a Python library that provides a simple way to define and run tasks.

It lets you write tasks in a familiar Python syntax and provides a command-line interface for running them. To use Invoke, you first need to install it using pip.

“`

pip install invoke

“`

Once installed, you can define your tasks using Python functions. Here is an example:

“`

from invoke import task

@task

def build():

print(“Building app…”)

@task

def deploy():

print(“Deploying app…”)

“`

To run these tasks, open the terminal, navigate to the directory containing the tasks file, and type `invoke build` or `invoke deploy`. These commands will execute the corresponding tasks defined in the Python code.

Packaging command-line applications:

Once you have written your CLI application, the next step is to package it. Packaging your application makes it easy to distribute and install on other machines.

Python provides built-in tools like setuptools and distutils for packaging and distributing Python modules. To distribute a CLI application, you need to define an entry point in your setup.py file.

Here’s an example setup.py file:

“`

from setuptools import setup, find_packages

setup(

name=”example”,

version=”0.1″,

packages=find_packages(),

entry_points={

‘console_scripts’: [‘app=example.app:main’]

}

)

“`

This setup.py file defines an app called “example,” and its entry point is set to “example.app:main.” This means that the command “app” will run the “main” function defined in the “example.app” module. To create a distributable package, run the following command:

“`

python setup.py sdist

“`

This command creates a source distribution file in the dist directory.

To install the package, use the following command:

“`

pip install dist/example-0.1.tar.gz

“`

This command installs the package, and the entry point is now available on the command line. Commands:

Overview of command implementation for each library:

All three libraries, argparse, docopt, and click, provide a way to define commands in Python syntax.

The implementation of commands varies slightly between the libraries. Argparse command implementation:

Argparse provides a way to define subcommands using `add_subparsers` method.

Here is an example:

“`

import argparse

def foo(args):

print(“Foo!”)

def bar(args):

print(“Bar!”)

parser = argparse.ArgumentParser()

subparsers = parser.add_subparsers()

parser_foo = subparsers.add_parser(“foo”)

parser_foo.set_defaults(func=foo)

parser_bar = subparsers.add_parser(“bar”)

parser_bar.set_defaults(func=bar)

args = parser.parse_args()

args.func(args)

“`

This code defines two subcommands, “foo” and “bar,” each with its own function. The `set_defaults` method sets the function that will be run when the subcommand is called.

Docopt command implementation:

Docopt uses the docstring of a Python file to define commands. Here is an example:

“`

“””

Program usage.

Usage:

program foo

program bar

Options:

-h –help Show this screen. “””

def main(args):

if args[“foo”]:

print(“Foo!”)

if args[“bar”]:

print(“Bar!”)

if __name__ == “__main__”:

from docopt import docopt

main(docopt(__doc__))

“`

In this code, we define two subcommands, “foo” and “bar,” within the program usage docstring using the syntax `program foo` and `program bar`.

The `docopt(__doc__)` method parses the docstring options and returns a dictionary containing the arguments. Click command implementation:

Click uses a decorator syntax to define commands.

Here is an example:

“`

import click

@click.group()

def cli():

pass

@cli.command()

def foo():

print(“Foo!”)

@cli.command()

def bar():

print(“Bar!”)

if __name__ == “__main__”:

cli()

“`

The `@click.group()` decorator creates a command group. Commands are then created using the `@cli.command()` decorator.

When the CLI application is run, the `if __name__ == “__main__”: cli()` line runs the CLI application. Conclusion:

In this article, we have learned about task-runner libraries and how to use Invoke to create and run tasks from the command line.

We have also learned about packaging CLI applications using Python’s built-in tools like setuptools and distutils. Lastly, we have discussed the implementation of commands in argparse, docopt, and click, and how to define them in Python syntax.

With this knowledge, you can build powerful CLI applications that automate complex tasks, are easy to distribute and install, and provide a fantastic user experience. Arguments:

Adding positional arguments:

Positional arguments are arguments that are passed to a CLI application without a flag or option.

Adding positional arguments in argparse is straightforward using the `add_argument` method. Here is an example:

“`

import argparse

parser = argparse.ArgumentParser()

parser.add_argument(“name”, help=”The name of the person.”)

parser.add_argument(“age”, type=int, help=”The age of the person.”)

args = parser.parse_args()

print(f”Name: {args.name}”)

print(f”Age: {args.age}”)

“`

This code defines two positional arguments, “name” and “age,” with their respective help messages. The order in which these arguments are passed on the CLI is significant, and they will be parsed in the same order and passed to args as attributes.

In Click, positional arguments are added as function arguments using the `@click.argument` decorator. Here is an example:

“`

import click

@click.command()

@click.argument(“name”)

@click.argument(“age”, type=int)

def example(name, age):

click.echo(f”Name: {name}”)

click.echo(f”Age: {age}”)

if __name__ == “__main__”:

example()

“`

This code defines two positional arguments, “name” and “age,” as function arguments. The `type` keyword argument specifies the type conversion for the age argument.

Accessing arguments in function logic:

Once we have defined positional arguments, we can access them in the function logic using the `args` namespace in argparse. Here is an example:

“`

import argparse

parser = argparse.ArgumentParser()

parser.add_argument(“name”, help=”The name of the person.”)

parser.add_argument(“age”, type=int, help=”The age of the person.”)

args = parser.parse_args()

if args.age < 18:

print(f”{args.name} is a minor.”)

else:

print(f”{args.name} is an adult.”)

“`

In this example, we access the “name” and “age” arguments in the function logic using the `args` namespace and perform a simple comparison to check if the person is a minor or an adult. Flags/Options:

Adding options and flags with argparse:

Options and flags are additional arguments that can be passed to our CLI applications.

We add them using the `add_argument` function in argparse. Here is an example:

“`

import argparse

parser = argparse.ArgumentParser()

parser.add_argument(“–verbose”, help=”Increase output verbosity”, action=”store_true”)

args = parser.parse_args()

if args.verbose:

print(“Verbose mode on.”)

“`

In this example, we use the `–verbose` option and set the action to “store_true” to store the Boolean value True when the option is passed. Overcoming limits of docopt for multiple defaults:

Docopt has limitations when it comes to multiple defaults for an option.

For example, an option with multiple default values will only be set to the first value. To overcome this limitation, we can use multiple options with the same name.

Here is an example:

“`

“””

Program usage. Usage:

program [options]

Options:

-o –option= Set option [default: value1]

–option= Set option [default: value2]

“””

args = docopt(__doc__)

if args[“–option”]:

options = args[“–option”]

else:

options = [“value1”, “value2”]

print(f”Options: {options}”)

“`

In this code, we define two options with the same name, but different default values.

If the user passes an option, that value will be used. If not, the default values will be used.

Adding options and flags with Click:

Click provides the `@click.option` decorator to add options and flags to our CLI application. Here is an example:

“`

import click

@click.command()

@click.option(“–verbose”, is_flag=True, help=”Increase output verbosity”)

def example(verbose):

if verbose:

click.echo(“Verbose mode on.”)

if __name__ == “__main__”:

example()

“`

In this code, we use the `@click.option` decorator to add the “verbose” flag to our CLI application. The `is_flag=True` option specifies that this is a Boolean flag.

Conclusion:

In this article, we have learned about the different types of arguments that we can pass to our CLI applications, including positional arguments and options/flags. We have seen how to add these types of arguments using argparse, docopt, and Click.

We have also discussed how to access these arguments in the function logic of our CLI applications. With this knowledge, we can build powerful and flexible CLI applications that can handle a wide range of inputs and options.

Version Option:

Adding a `–version` argument to show the version number is a common requirement for CLI applications. It provides users with the essential information about the version of the software they’re using.

In this section, we’ll discuss how to add a `–version` argument to CLI applications using argparse, docopt, and Click. Implementation with argparse:

Argparse provides a built-in way to add a `–version` argument using the `add_argument` function.

The `add_argument` function has an `action` parameter with a `version` option that sets the version number. Here is an example:

“`

import argparse

parser = argparse.ArgumentParser()

parser.add_argument(‘–version’, action=’version’, version=’1.0′)

args = parser.parse_args()

if args.version:

print(args.version)

“`

In this example, we add a `–version` argument to the parser and set the version number as `1.0`. The `action=’version’` part of the code sets the action of the argument to `version`, which prints the version number and exits the program.

Implementation with docopt:

In docopt, we can define the `–version` argument as a special option. Here’s an example:

“`

“””

Program usage.

Usage:

program [options]

Options:

–version Show version number. “””

VERSION = “1.0”

args = docopt(__doc__, version=VERSION, options_first=True)

if args[“–version”]:

print(f”Version {VERSION}”)

“`

In this example, we define the `–version` argument in the docstring using the same syntax we use for other options.

The `version` keyword argument sets the version number to `1.0`. The `options_first=True` keyword argument in the `docopt` method tells docopt to stop parsing options once it finds a non-option argument.

In the last line, we check if the `–version` option was passed and print the version number. Implementation with Click:

In Click, we can use the `@click.version_option` decorator to add the `–version` option.

Here’s an example:

“`

import click

@click.command()

@click.version_option(version=’1.0′)

def example():

pass

if __name__ == “__main__”:

example()

“`

In this example, we add the `@click.version_option` decorator to the CLI function. The `version` keyword argument sets the version number to `1.0`.

Popular Posts