Python's builtins wrapped inside rust-like Result type
Warning
This library doesn't depend on original python Result library, instead it depends on my fork which is up-to-date with the one maintained by @montasaurus, as per this README is written, it's still labeled as experimental and unstable, so use this library at your own risk!
Install the package from PyPi using uv:
uv add safe-builtinsor install it directly from master branch on github for the latest update
uv add git+https://github.com/kkkfasy/safe-builtinsWarning
Since uv doesnt support downloading transitive dependency from custom registry (in this case github), you need to run
uv add git+https://github.com/kkkfasy/resultyou dont need to run this if you install from github directly
This library provides safe wrappers for Python's built-in functions using the Result type from the montasaurus/result library. Instead of raising exceptions, these functions return a Result that either contains the successful value (Ok) or the caught exception (Err).
This approach eliminates the need for extensive try/except blocks and makes error handling more explicit and functional in style.
Each Python builtin function has a corresponding safe_ prefixed version:
from safe_builtins import safe_int, safe_open, safe_len
# Instead of raising ValueError, returns Err(ValueError(...))
result = safe_int("not a number")
# Returns Ok(42)
result = safe_int("42")
# Instead of raising FileNotFoundError, returns Err(FileNotFoundError(...))
result = safe_open("non_existent_file.txt")
# Returns Ok(file_object)
result = safe_open("existing_file.txt")
# Instead of raising TypeError, returns Err(TypeError(...))
result = safe_len(123) # integers don't have length
# Returns Ok(3)
result = safe_len([1, 2, 3])You can check if a result is successful or contains an error:
from safe_builtins import safe_int
from result import Ok, Err
result = safe_int("42")
# Using isinstance checks
if isinstance(result, Ok):
value = result.unwrap()
print(f"Got value: {value}")
elif isinstance(result, Err):
error = result.unwrap_err()
print(f"Got error: {error}")
# Using is_ok/is_err methods
if result.is_ok():
value = result.unwrap()
print(f"Got value: {value}")
elif result.is_err():
error = result.unwrap_err()
print(f"Got error: {error}")from safe_builtins import safe_int
from result import Ok
result = safe_int("42")
# Get the value or raise an exception if it's an error
value = result.unwrap()
# Get the value or a default if it's an error
value = result.unwrap_or(0)
# Get the value or compute a default if it's an error
value = result.unwrap_or_else(lambda err: 0)
# Convert to optional (None if error)
optional_value = result.ok()from safe_builtins import safe_int, safe_open
from result import Ok
# Chain operations that might fail
result = (
safe_int("42")
.map(lambda x: x * 2) # Only executed if the result is Ok
.map_err(lambda err: f"Error processing number: {err}") # Only executed if the result is Err
)
# Process file contents safely
result = (
safe_open("data.txt")
.map(lambda f: f.read()) # Read file contents
.map(lambda contents: contents.splitlines()) # Split into lines
.map(lambda lines: len(lines)) # Count lines
)The following Python builtins are available as safe versions:
safe_abssafe_aitersafe_allsafe_anysafe_anextsafe_asciisafe_binsafe_breakpointsafe_bytearraysafe_bytessafe_chrsafe_compilesafe_complexsafe_delattrsafe_dictsafe_dirsafe_divmodsafe_enumeratesafe_evalsafe_execsafe_filtersafe_floatsafe_formatsafe_frozensetsafe_getattrsafe_hashsafe_hexsafe_idsafe_inputsafe_intsafe_isinstancesafe_issubclasssafe_itersafe_lensafe_listsafe_mapsafe_maxsafe_memoryviewsafe_minsafe_nextsafe_objectsafe_octsafe_opensafe_ordsafe_powsafe_rangesafe_reversedsafe_roundsafe_setsafe_setattrsafe_slicesafe_sortedsafe_staticmethodsafe_strsafe_sumsafe_supersafe_tuplesafe_typesafe_varssafe_zipsafe_importsafe_bool
- result - The underlying Result type implementation
- returns - Another functional approach to error handling in Python
MIT