Invoke

Language: Python

CLI/Utils

Invoke was created by the same team behind Fabric to provide a standalone Pythonic task execution tool. It simplifies running and organizing shell commands, tasks, and workflows in a maintainable way, allowing developers to automate build systems, deployment scripts, and other routine tasks.

Invoke is a Python task execution library that provides a clean, high-level API for defining and running shell-oriented tasks from Python scripts. It is designed to help automate repetitive workflows, build processes, and command-line operations.

Installation

pip: pip install invoke
conda: conda install -c conda-forge invoke

Usage

Invoke allows you to define tasks as Python functions and execute them via the command line. Tasks can accept arguments, run shell commands, and be organized hierarchically. It provides features like namespaces, command-line parsing, and pre/post task hooks.

Defining a simple task

from invoke import task

@task
def hello(c):
    print('Hello, Invoke!')

Defines a simple task named `hello`. Tasks are decorated with `@task` and receive a context `c` for running commands.

Running a task from the CLI

# Terminal command:
# inv hello

Executes the `hello` task defined in `tasks.py` using the `inv` command-line tool.

Task with arguments

from invoke import task

@task
def greet(c, name='World'):
    print(f'Hello, {name}!')

Defines a task that accepts an argument `name`. You can call it with `inv greet --name=Alice`.

Running shell commands

from invoke import task

@task
def list_files(c):
    c.run('ls -l')

Uses the context `c` to run shell commands directly from a task.

Task namespaces

from invoke import Collection, task

@task
def clean(c):
    c.run('rm -rf build/')

ns = Collection()
ns.add_task(clean, 'clean')

Organizes tasks into namespaces for better project structure and management.

Pre/post task hooks

from invoke import task

@task(pre=[setup])
def build(c):
    c.run('make')

Executes a `setup` task automatically before running the `build` task.

Error Handling

invoke.exceptions.Exit: Occurs when a shell command executed via `c.run()` exits with a non-zero status. Handle by using `warn=True` or try/except.
NameError: name 'task' is not defined: Ensure `from invoke import task` is included at the top of your tasks file.
No tasks found: Make sure the tasks are defined in a `tasks.py` file or properly added to a namespace and the `inv` command is run in the correct directory.

Best Practices

Keep tasks small and modular for clarity and maintainability.

Use namespaces to group related tasks together.

Use context (`c`) to run shell commands instead of using `os.system`.

Document tasks with docstrings so that `inv --list` provides helpful descriptions.

Combine with version control and CI/CD pipelines to automate build and deployment workflows.