PyInvoke is a Python task execution tool that helps you define and run command-line tasks. Think of it as a Pythonic alternative to Makefiles.
pip install invokefrom invoke import task
@task
def hello(c):
"""Say hello"""
print("Hello, World!")
@task
def build(c):
"""Build the project"""
c.run("python setup.py build")
@task
def test(c):
"""Run tests"""
c.run("pytest tests/")# List available tasks
invoke --list
# Run a task
invoke hello
invoke build
invoke test@task
def greet(c, name="World"):
"""Greet someone by name"""
print(f"Hello, {name}!")invoke greet --name=Alice
invoke greet -n Bob@task
def clean(c):
"""Clean build artifacts"""
c.run("rm -rf build/ dist/")
@task(pre=[clean])
def build(c):
"""Build after cleaning"""
c.run("python setup.py build")@task
def deploy(c):
c.run("git push origin main")
c.run("ssh server 'sudo systemctl restart app'")@task
def serve(c, port=8000):
"""Start development server"""
with c.cd('src'):
c.run(f"python -m http.server {port}")It has many methods, for configurations, for example:
- c.run(command)
- c.sudo(command)
- c.cd(path)
- c.prefix(command)
- c.config.run.echo
- c.config.project_name
Executes shell commands:
@task
def test(c):
c.run("pytest tests/")
c.run("flake8 .")Runs commands with sudo privileges:
@task
def install(c):
c.sudo("apt-get install nginx")Changes directory (as a context manager):
@task
def build(c):
with c.cd('frontend'):
c.run("npm run build")
## c.prefix(command)
Prefixes subsequent commands:
```python
@task
def venv_test(c):
with c.prefix('source venv/bin/activate'):
c.run("pip install -r requirements.txt")
c.run("pytest")The Context object also holds configuration:
@task
def info(c):
print(c.config.run.echo) # Access configuration
print(c.config.project_name) # Custom config values@task
def deploy(c):
# Hide output
c.run("git push", hide=True)
# Don't raise exception on failure
result = c.run("test -f file.txt", warn=True)
# Capture output
result = c.run("git rev-parse HEAD", hide=True)
print(f"Current commit: {result.stdout.strip()}")
# Run in pseudoterminal (for interactive commands)
c.run("vim file.txt", pty=True)c.run() returns a Result object with useful properties:
@task
def check(c):
result = c.run("echo 'Hello'", hide=True)
print(result.stdout) # "Hello\n"
print(result.stderr) # ""
print(result.return_code) # 0
print(result.ok) # True (return_code == 0)
print(result.failed) # FalseThe Context object (c) is your interface to:
- Execute commands (run, sudo)
- Control execution environment (cd, prefix)
- Access configuration (c.config)
- Handle command results (return values from run())
It's the glue that connects your Python task definitions to actual system commands!
Check the official docs for namespaces, configuration, and error handling!