Outcome
Outcome is a Python library extracted from the Trio project, designed to capture the outcome (return value or raised exception) of both synchronous and asynchronous Python function calls. It provides a standardized way to pass around results that might otherwise be exceptions, facilitating structured error handling. The current version is 1.3.0.post0, with releases occurring periodically to add features and address issues.
Warnings
- gotcha An `Outcome` object can only be unwrapped (accessed via `.unwrap()` or `.error()`/`.value()`) once. Subsequent attempts to unwrap or access its contents will raise an `outcome.AlreadyUsedError`.
- gotcha The `outcome` library provides `Value` and `Error` classes, which are not exceptions themselves. Do not attempt to catch `outcome.Error` or `outcome.Value` directly using `try...except`. Instead, use `outcome_obj.is_error()` or `outcome_obj.is_value()` to check the type of outcome, and then `unwrap()` within a `try...except` block if you expect exceptions, or `error()`/`value()` to access the content.
- gotcha As of version 1.3.0, the exception frame generated within `capture()` and `acapture()` has been removed from the traceback on Python 3. This can make debugging slightly different as the `outcome` internal frames will no longer appear in the stack trace.
Install
-
pip install outcome
Imports
- capture
from outcome import capture
- acapture
from outcome import acapture
- Outcome
from outcome import Outcome
- Value
from outcome import Value
- Error
from outcome import Error
- AlreadyUsedError
from outcome import AlreadyUsedError
Quickstart
import outcome
import asyncio
def successful_function():
return "Success!"
def failing_function():
raise ValueError("Something went wrong!")
async def async_successful_function():
await asyncio.sleep(0.01)
return "Async Success!"
async def async_failing_function():
await asyncio.sleep(0.01)
raise RuntimeError("Async operation failed!
")
# Example 1: Synchronous capture
sync_success_outcome = outcome.capture(successful_function)
print(f"Sync Success: {sync_success_outcome.unwrap()}")
sync_failure_outcome = outcome.capture(failing_function)
try:
sync_failure_outcome.unwrap()
except ValueError as e:
print(f"Sync Failure caught: {e}")
# Example 2: Asynchronous capture
async def main():
async_success_outcome = await outcome.acapture(async_successful_function)
print(f"Async Success: {async_success_outcome.unwrap()}")
async_failure_outcome = await outcome.acapture(async_failing_function)
try:
async_failure_outcome.unwrap()
except RuntimeError as e:
print(f"Async Failure caught: {e}")
# Demonstrating AlreadyUsedError (Outcome objects can only be unwrapped once)
try:
print(sync_success_outcome.unwrap())
except outcome.AlreadyUsedError as e:
print(f"Caught expected error: {e}")
asyncio.run(main())