Skip to main content

better-result-py

Inspired by better-result

Yet another implementation of Rust's Result type: minimal, dependency-free, and fully-typed. Wraps synchronous and asynchronous functions so exceptions become values rather than control flow.

Installation

# with uv
uv add better-result-py
# with pip
pip install better-result-py

Usage

Synchronous

Wrap any callable with Result. If the function raises, ok is Unset and err holds the exception. If it succeeds, ok holds the value and err is None.

from better_result import Result

def divide(a: int, b: int) -> float:
    return a / b

result = Result(divide, 10, 2)
result.is_ok()   # True
result.ok        # 5.0
result.err       # None

result = Result(divide, 10, 0)
result.is_ok()   # False
result.err       # ZeroDivisionError(...)

Asynchronous

AsyncResult works the same way for async functions.

import asyncio
from better_result import AsyncResult

async def fetch_data(url: str) -> str:
    ...  # may raise

result = await AsyncResult(fetch_data, "https://example.com")

if result.is_ok():
    print(result.ok)
else:
    print(result.err)

Explicit Ok / Err construction

For control-flow patterns where you want to return a typed result directly (without wrapping a callable) use Ok and Err.

from better_result import Ok, Err, BaseResult

def divide(a: int, b: int) -> BaseResult[float]:
    if b == 0:
        return Err("division by zero")
    return Ok(a / b)

result = divide(10, 2)
result.is_ok()   # True
result.ok        # 5.0

result = divide(10, 0)
result.is_err()  # True
result.err       # ResultError("division by zero")

Err accepts either a plain string message (wrapped in ResultError) or an existing exception via the err keyword argument:

Err("something went wrong")          # error_message form
Err(err=ValueError("bad value"))     # exception form

Extracting values

unwrap()

Returns the value or raises the original exception (or UnsetError if the result is unset).

value = Result(divide, 10, 2).unwrap()   # 5.0
Result(divide, 10, 0).unwrap()           # raises ZeroDivisionError

unwrap_or(default)

Returns the value or falls back to a default on error.

value = Result(divide, 10, 0).unwrap_or(0.0)  # 0.0

expect(message)

Like unwrap(), but always raises ExpectError with a custom message (preserving the original exception as __cause__).

result = Result(divide, 10, 0)
result.expect("division must succeed")  # raises ExpectError("division must succeed")

API reference

Method Description
is_ok() -> bool True if no error and value is set
is_err() -> bool True if an error occurred or value is unset
unwrap() -> T Return value or raise
unwrap_or(default: T) -> T Return value or default
expect(message: str) -> T Return value or raise ExpectError

Requirements

Python 3.10 or higher. No runtime dependencies.

Roadmap

Find the full roadmap here

Metadata

Release files for better-result-py 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for better-result-py 1.1.0
File Size Uploaded Provenance Actions
better_result_py-1.1.0.tar.gz 3.6 kB Without provenance Details for better_result_py-1.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for better-result-py 1.1.0
File Interpreter ABI Platform Actions
better_result_py-1.1.0-py3-none-any.whl Python 3 none any Details for better_result_py-1.1.0-py3-none-any.whl

Total release size: 8.1 kB

Release files / better_result_py-1.1.0.tar.gz

Download URL better_result_py-1.1.0.tar.gz
Size 3.6 kB
Tags Source
SHA-256 checksum
How to use checksums
b73494e0692efda9d6fd3ea1304093a35c18b94633bfcfaec37aab80e951f2e4
BLAKE2b-256 checksum
How to use checksums
f9d2c02f5be83ac4e52b95fbe9673715c1d3901863ec5ee98db94f09f3f2abe0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / better_result_py-1.1.0-py3-none-any.whl

Download URL better_result_py-1.1.0-py3-none-any.whl
Size 4.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
585df8a5ceca37a5891f1e4989147b7cbc7657ddfaba8f6f44a0d766b2a2b392
BLAKE2b-256 checksum
How to use checksums
4d2c58bb760c184da697e1e4f6d1c4ee21e875fb133955d6c9ad4e8aabd5be13
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for better-result-py 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page