Introduction to Defekt
Defekt is a powerful and flexible error handling library designed to make managing errors in your applications more efficient and effective.
In this article, we will dive into the various APIs offered by Defekt, providing useful code snippets and a comprehensive app example to help you master error handling with this impressive library.
Defining Custom Errors
With Defekt, you can easily define custom error types:
import defekt
# Define custom errors
class FileNotFound(defekt.Error):
pass
class PermissionDenied(defekt.Error):
pass
Raising Custom Errors
You can raise these custom errors when appropriate:
def read_file(file_path):
if not os.path.exists(file_path):
raise FileNotFound(f"File not found: {file_path}")
if not os.access(file_path, os.R_OK):
raise PermissionDenied(f"Permission denied: {file_path}")
with open(file_path, 'r') as file:
return file.read()
Handling Custom Errors
It’s simple to catch and handle these errors in your code:
try:
content = read_file('example.txt')
except FileNotFound as e:
print(e)
except PermissionDenied as e:
print(e)
Using Either for Error Handling
The Either type is an alternative way to handle errors:
from defekt import Either, Ok, Err
def read_file(file_path) -> Either[FileNotFound, str]:
if not os.path.exists(file_path):
return Err(FileNotFound(f"File not found: {file_path}"))
with open(file_path, 'r') as file:
return Ok(file.read())
result = read_file('example.txt')
if result.is_ok():
print(result.unwrap())
else:
print(result.unwrap_err())
API Examples
Here are more API examples to demonstrate the flexibility of Defekt:
# Example 1: Using match method
def process_result(result: Either[ErrorType, ValueType]):
result.match(
ok=lambda value: process_value(value),
err=lambda error: handle_error(error)
)
# Example 2: Using try-catch blocks with Defekt errors
def safe_divide(a, b):
try:
if b == 0:
raise ZeroDivisionError('Division by zero')
return a / b
except ZeroDivisionError as e:
return Err(e)
result = safe_divide(10, 0)
if result.is_err():
print(f"Error occurred: {result.unwrap_err()}")
# Example 3: Defining multiple errors
class NetworkError(defekt.Error):
pass
class TimeoutError(NetworkError):
pass
class ConnectionError(NetworkError):
pass
App Example Using Defekt APIs
Let’s create a simple CLI app that demonstrates the usage of Defekt APIs:
import defekt
from defekt import Err, Ok
import os
# Define custom errors for the app
class AppError(defekt.Error):
pass
class InvalidArgumentError(AppError):
pass
class FileProcessingError(AppError):
pass
# Function to process a file
def process_file(file_path) -> Either[AppError, str]:
if not file_path:
return Err(InvalidArgumentError('No file path provided'))
try:
with open(file_path, 'r') as file:
return Ok(file.read())
except FileNotFoundError:
return Err(FileProcessingError(f"File not found: {file_path}"))
except Exception as e:
return Err(FileProcessingError(str(e)))
# CLI app entry point
if __name__ == '__main__':
import sys
if len(sys.argv) < 2:
print("Usage: python app.py ")
sys.exit(1)
file_path = sys.argv[1]
result = process_file(file_path)
if result.is_ok():
print("File content:")
print(result.unwrap())
else:
print("Error occurred:")
print(result.unwrap_err())
With this simple CLI app, you can see how Defekt helps in handling errors effectively, making your code cleaner and more maintainable.
Hash: 292768653285dc5eb625d891fda888f66f4ad82e2b8018c57cae1f7db6f145d5