Outcome

raw JSON →
1.3.0.post0 verified Tue May 12 auth: no python install: verified quickstart: stale

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.

pip install outcome
error outcome.AlreadyUsedError
cause An `Outcome` object's `unwrap()` method can only be called once to retrieve its result or re-raise its exception; subsequent calls will raise `AlreadyUsedError`.
fix
Store the result of the first unwrap() call in a variable, or use the outcome.Executor context manager for automatic handling of used outcomes.
error AttributeError: 'Outcome' object has no attribute 'value'
cause This occurs when attempting to access a direct 'value' attribute on an `Outcome` object that holds an exception (an error outcome), rather than a successful result.
fix
Before accessing the value, check if the Outcome represents a successful result using result.is_ok(). If true, use result.unwrap() to safely retrieve the value.
error AttributeError: 'Outcome' object has no attribute 'exception'
cause This occurs when attempting to access a direct 'exception' attribute on an `Outcome` object that holds a successful result, rather than an exception (an error outcome).
fix
Before accessing the exception, check if the Outcome represents an error using result.is_error(). If true, use result.unwrap() within a try-except block to catch the contained exception.
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`.
fix Store the result of `outcome.unwrap()` if you need to use the value multiple times, or ensure `Outcome` objects are only unwrapped a single time within your logic.
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.
fix Refactor error handling to check `is_error()`/`is_value()` methods on the `Outcome` object before attempting to unwrap, or wrap the `unwrap()` call in a standard Python `try...except` block for the actual exceptions your captured function might raise.
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.
fix Be aware of this change when inspecting tracebacks. The original exception will still be present, but the path through `outcome`'s internal capturing logic will be omitted.
gotcha A SyntaxError: EOL while scanning string literal indicates an unclosed string literal, often due to a missing closing quote or improper multiline string definition. This is a basic Python syntax error and not related to library-specific runtime issues.
fix Examine the specified line in the Python script for unclosed string literals. Ensure all string literals have matching opening and closing quotes (single, double, or triple) and are correctly formatted for multiline strings.
gotcha The provided script contains a `SyntaxError: unterminated string literal`. This error occurs when a string literal is not properly closed with a matching quote, leading to a parsing error before the code can even execute.
fix Review the script for missing closing quotes or other syntax errors, specifically at `/script.py`, line 16, and ensure all string literals are correctly terminated.
python os / libc status wheel install import disk
3.10 alpine (musl) wheel - 0.07s 18.4M
3.10 alpine (musl) - - 0.08s 18.4M
3.10 slim (glibc) wheel 1.5s 0.05s 19M
3.10 slim (glibc) - - 0.05s 19M
3.11 alpine (musl) wheel - 0.11s 20.3M
3.11 alpine (musl) - - 0.12s 20.3M
3.11 slim (glibc) wheel 1.7s 0.09s 21M
3.11 slim (glibc) - - 0.09s 21M
3.12 alpine (musl) wheel - 0.11s 12.1M
3.12 alpine (musl) - - 0.11s 12.1M
3.12 slim (glibc) wheel 1.5s 0.10s 13M
3.12 slim (glibc) - - 0.09s 13M
3.13 alpine (musl) wheel - 0.09s 11.9M
3.13 alpine (musl) - - 0.09s 11.8M
3.13 slim (glibc) wheel 1.5s 0.09s 12M
3.13 slim (glibc) - - 0.09s 12M
3.9 alpine (musl) wheel - 0.06s 17.9M
3.9 alpine (musl) - - 0.07s 17.9M
3.9 slim (glibc) wheel 1.8s 0.05s 18M
3.9 slim (glibc) - - 0.06s 18M

This quickstart demonstrates how to use `outcome.capture` for synchronous functions and `outcome.acapture` for asynchronous functions, handling both successful returns and raised exceptions. It also illustrates the `AlreadyUsedError` which is raised if an `Outcome` object's value or error is attempted to be accessed more than once.

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())