• SSC Lunch Time Python
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Lunchtime Python #3: Click¶

Presenter: Dominic Kempf, Scientific Software Center

Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary.

Command Line Interfaces: Why?¶

Natural evolution of a piece of research software in Python:

  • Starts on a Jupyter notebook playground
  • At some point freezes into a script for long term use
  • (Automated) Application to a wider range of usage scenarios

For the last step, good Command Line Interface (CLI) is very helpful. Important aspects:

  • Easy addition into existing code
  • Few lines of code to ease maintenance and focus on the scientific part
  • Good help text generation

How not to do it¶

We get access to command line arguments similar to C through sys.argv:

# DON'T DO THIS!
import sys

inputfile = sys.argv[1]
print(f"Calculating statistics from {inputfile}")

Why is this bad?

  • No help text generation
  • No validation of arguments
  • Prone to errors in argument indexing
  • Logic for non-string and optional arguments becomes quickly unwieldy

The standard libraries argparse and optparse are better options, but there is even better.

Click: A beautiful, opinionated approach¶

import click

@click.command()
@click.argument("inputfile", type=click.Path(exists=True))
def stats(inputfile):
    """Read data from the given INPUTFILE and calculate useful statistics"""
    click.echo(f"Calculating statistics from {inputfile}")

# This allows use of this Python file both for imports and for the CLI
if __name__ == "__main__":
    stats()

Arguments vs. Options¶

Arguments are positional and only too a small extent optional or defaultable. Use them only for absolute essential, self-explanatory input. To customize your script's behavious options are the better choice:

import click

@click.command()
@click.option(
    "--input",
    type=click.Path(exists=True),
    default="input.txt",
    help="The data file to read from",
)
@click.option(
    "--verbose/--no-verbose", type=bool, help="Whether to output intermediate results"
)
def stats(verbose, input):
    """Read data and calculate useful statistics"""
    if verbose:
        click.echo("Started the CLI script")
    click.echo(f"Calculating statistics from {input}")

if __name__ == "__main__":
    stats()

Composability of commands¶

Add subcommand structure by reusing previously defined commands:

@click.group()
def main():
    pass

@click.command()
def preprocess():
    click.echo("Apply preprocessing")

main.add_command(stats)
main.add_command(preprocess)

if __name__ == "__main__":
    main()

This mechanism is very powerful: arbitrary nesting, runtime extension e.g. through plugins etc.

Setuptools integration¶

As software becomes more mature, it is also advisable to package and distribute it as a Python package. Click easily integrates with setuptools as well using the entrypoints mechanism:

# In setup.py
setup(entry_points={"console_scripts": ["myscript = mypackage.mymodule:myclifunction"]})
# In setup.cfg
[options.entry_points]
console_scripts =
    myscript = mypackage.mymodule:myclifunction

Further information about click¶

Today's presentation can be found on the Lunch Time Python website: https://ssciwr.github.io/lunch-time-python/

For further information, see also the (very good) Click documentation

For questions to the Scientific Software Center, please write us to ssc@iwr.uni-heidelberg.de

Lunch Time Python Session #4¶

Library options, please vote now:

  • itertools is a standard library that implements a number of iterator building blocks inspired by functional programming languages.
  • pytest The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries.
  • matplotlib Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations in Python