Last modified: Aug 12, 2025 By Alexander Williams

Python Typer Exit Codes and Output Best Practices

Building CLI apps with Python Typer? Proper exit codes and output handling make your tools professional. This guide covers best practices.

Understanding Exit Codes in Typer

Exit codes tell the shell if your CLI succeeded or failed. Typer uses standard Unix conventions.

0 means success. Any non-zero value indicates an error. Common codes include 1 for general errors and 2 for misuse.


import typer

app = typer.Typer()

@app.command()
def greet(name: str):
    if not name:
        typer.echo("Error: Name required", err=True)
        raise typer.Exit(code=1)
    typer.echo(f"Hello {name}")

if __name__ == "__main__":
    app()

Stdout vs Stderr: When to Use Each

stdout is for normal program output. stderr is for errors and diagnostics.

Typer's typer.echo() lets you choose where output goes. Set err=True for stderr.


@app.command()
def calculate(value: int):
    if value < 0:
        typer.echo("Error: Positive numbers only", err=True)
        raise typer.Exit(1)
    
    result = value * 2
    typer.echo(f"Result: {result}")  # stdout by default

Common Exit Code Patterns

Use consistent exit codes. Here are common patterns:

  • 0: Success
  • 1: General error
  • 2: Command line syntax error
  • 3: Missing dependency
  • 4: Permission denied

For complex apps, document your exit codes in help text. See our Python Typer Help Text Guide.

Advanced Error Handling

Combine exit codes with Typer's error handling. Use typer.Abort() for critical failures.


@app.command()
def process_file(path: str):
    try:
        with open(path) as f:
            content = f.read()
    except FileNotFoundError:
        typer.echo(f"Error: File {path} not found", err=True)
        raise typer.Abort()
    
    typer.echo(f"Processed {len(content)} bytes")

For more on errors, check our Python Typer Error Handling Guide.

Testing Your Output Handling

Verify your output goes to the right stream. Capture stdout and stderr in tests.


from typer.testing import CliRunner

runner = CliRunner()
result = runner.invoke(app, ["greet", ""])

assert result.exit_code == 1
assert "Error: Name required" in result.stderr

Best Practices Summary

Follow these rules for professional CLI apps:

  • Use 0 for success, non-zero for errors
  • Send normal output to stdout
  • Send errors and diagnostics to stderr
  • Document your exit codes
  • Be consistent across commands

For more Typer features, see our Subcommands Guide.

Conclusion

Proper exit codes and output streams make your CLI tools work better in scripts and pipelines. Typer makes it easy to follow Unix conventions.

Remember: success=0, errors=non-zero, normal output=stdout, errors=stderr. Keep your CLI behavior predictable and documented.