{"id":675,"library":"outcome","title":"Outcome","description":"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.","status":"active","version":"1.3.0.post0","language":"python","source_language":"en","source_url":"https://github.com/python-trio/outcome","tags":["concurrency","error-handling","trio","result-type","async"],"install":[{"cmd":"pip install outcome","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Required runtime environment.","package":"python","optional":false}],"imports":[{"symbol":"capture","correct":"from outcome import capture"},{"symbol":"acapture","correct":"from outcome import acapture"},{"symbol":"Outcome","correct":"from outcome import Outcome"},{"symbol":"Value","correct":"from outcome import Value"},{"symbol":"Error","correct":"from outcome import Error"},{"note":"This exception is raised if an Outcome object is unwrapped more than once.","symbol":"AlreadyUsedError","correct":"from outcome import AlreadyUsedError"}],"quickstart":{"code":"import outcome\nimport asyncio\n\ndef successful_function():\n    return \"Success!\"\n\ndef failing_function():\n    raise ValueError(\"Something went wrong!\")\n\nasync def async_successful_function():\n    await asyncio.sleep(0.01)\n    return \"Async Success!\"\n\nasync def async_failing_function():\n    await asyncio.sleep(0.01)\n    raise RuntimeError(\"Async operation failed!\n\")\n\n# Example 1: Synchronous capture\nsync_success_outcome = outcome.capture(successful_function)\nprint(f\"Sync Success: {sync_success_outcome.unwrap()}\")\n\nsync_failure_outcome = outcome.capture(failing_function)\ntry:\n    sync_failure_outcome.unwrap()\nexcept ValueError as e:\n    print(f\"Sync Failure caught: {e}\")\n\n# Example 2: Asynchronous capture\nasync def main():\n    async_success_outcome = await outcome.acapture(async_successful_function)\n    print(f\"Async Success: {async_success_outcome.unwrap()}\")\n\n    async_failure_outcome = await outcome.acapture(async_failing_function)\n    try:\n        async_failure_outcome.unwrap()\n    except RuntimeError as e:\n        print(f\"Async Failure caught: {e}\")\n\n    # Demonstrating AlreadyUsedError (Outcome objects can only be unwrapped once)\n    try:\n        print(sync_success_outcome.unwrap()) \n    except outcome.AlreadyUsedError as e:\n        print(f\"Caught expected error: {e}\")\n\nasyncio.run(main())\n","lang":"python","description":"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."},"warnings":[{"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.","message":"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`.","severity":"gotcha","affected_versions":"All versions"},{"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.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"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.","message":"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.","severity":"gotcha","affected_versions":">=1.3.0"},{"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.","message":"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.","severity":"gotcha","affected_versions":"All versions"},{"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.","message":"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.","severity":"gotcha","affected_versions":"All Python versions"}],"env_vars":null,"last_verified":"2026-05-12T17:44:43.190Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"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.","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`.","error":"outcome.AlreadyUsedError"},{"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.","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.","error":"AttributeError: 'Outcome' object has no attribute 'value'"},{"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.","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).","error":"AttributeError: 'Outcome' object has no attribute 'exception'"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":"1.3.0.post0","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.7,"disk_size":"18.4M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.08,"mem_mb":2.7,"disk_size":"18.4M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.05,"mem_mb":2.7,"disk_size":"19M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.05,"mem_mb":2.7,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":2.7,"disk_size":"20.3M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.12,"mem_mb":2.7,"disk_size":"20.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.7,"import_time_s":0.09,"mem_mb":2.7,"disk_size":"21M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":2.7,"disk_size":"21M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":2.7,"disk_size":"12.1M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.11,"mem_mb":2.7,"disk_size":"12.1M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.1,"mem_mb":2.7,"disk_size":"13M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":2.7,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":2.9,"disk_size":"11.9M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":2.9,"disk_size":"11.8M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.5,"import_time_s":0.09,"mem_mb":2.7,"disk_size":"12M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.09,"mem_mb":2.7,"disk_size":"12M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":2.6,"disk_size":"17.9M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.07,"mem_mb":2.6,"disk_size":"17.9M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":" $EXIT -eq 0 ","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":1.8,"import_time_s":0.05,"mem_mb":2.6,"disk_size":"18M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.06,"mem_mb":2.6,"disk_size":"18M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}