Click
Click ('Command Line Interface Creation Kit') is a Python package for creating composable, beautiful command-line interfaces with minimal boilerplate. It uses a decorator-based API to turn functions into CLI commands with automatic help page generation, argument/option parsing, type coercion, and shell completion. Current version is 8.3.1 (latest stable); the project follows a feature-release / fix-release cadence under the Pallets organization, with feature releases (e.g. 8.2.0, 8.3.0) potentially introducing deprecations or breaking changes and patch releases (e.g. 8.3.1) being safe upgrades.
Warnings
- breaking Python 3.7, 3.8, and 3.9 support was dropped in Click 8.2.0. Projects running on those versions must pin to click<8.2.
- deprecated BaseCommand and MultiCommand are deprecated since 8.2.0. Subclassing or isinstance-checking either will emit DeprecationWarnings and will break in a future major release.
- deprecated click.__version__ is deprecated since 8.2.0. Accessing it emits a DeprecationWarning.
- breaking click.get_terminal_size was removed in 8.1.0. Any code importing it from click will raise ImportError. Third-party packages that imported it (e.g. older spaCy) broke on upgrade.
- gotcha CliRunner.invoke() catches ALL exceptions by default (catch_exceptions=True), silently swallowing bugs. Tests may pass with exit_code != 0 if result.exception is not inspected.
- gotcha CliRunner is not thread-safe and mutates global interpreter state (sys.stdout, sys.stdin). Do not use it in threaded or async test suites without isolation.
- gotcha standalone_mode=True (the default) means Click calls sys.exit() after command execution, converting return values to exit codes. Calling a click command directly in application code without standalone_mode=False will terminate the process.
Install
-
pip install click
Imports
- click (namespace)
import click
- CliRunner
from click.testing import CliRunner
- Command
from click import Command
- Group
from click import Group
- get_terminal_size
import shutil; shutil.get_terminal_size()
- shell_complete (parameter)
@click.command() @click.option('--name', shell_complete=my_complete_fn)
Quickstart
import click
from click.testing import CliRunner
@click.group()
@click.option('--verbose', is_flag=True, default=False, help='Enable verbose output.')
@click.pass_context
def cli(ctx, verbose):
"""My CLI tool."""
ctx.ensure_object(dict)
ctx.obj['verbose'] = verbose
@cli.command()
@click.option('--count', default=1, show_default=True, help='Number of greetings.')
@click.option('--name', prompt='Your name', help='Person to greet.')
@click.pass_context
def greet(ctx, count, name):
"""Greet NAME a number of times."""
for _ in range(count):
click.echo(f"Hello, {name}!")
if ctx.obj.get('verbose'):
click.echo(f"(verbose mode, greeted {count} time(s))")
if __name__ == '__main__':
# Direct invocation
cli()
# --- Testing ---
def test_greet():
runner = CliRunner()
result = runner.invoke(cli, ['greet', '--name', 'World', '--count', '2'])
assert result.exit_code == 0, result.output
assert result.output.count('Hello, World!') == 2
test_greet()
click.echo('Quickstart test passed.')