Bringing Raised Exceptions Back From the Dead As New Exceptions.
zombie-py is a Python library that simplifies the process of transforming and re-raising exceptions. It provides a context manager and decorator for handling exceptions, allowing you to define custom transformations for exceptions. zombie-py is designed to make it easier to handle exceptions in Python by providing a simple and flexible way to transform and re-raise exceptions.
pip install zombie-py
from zombie import ExceptionTransformation, Reraise transform = ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, ), # Using as a context manager with multiple transforms with Reraise(transform): raise KeyError('Original error message')
Traceback (most recent call last):
File "example.py", line 20, in <module>
raise KeyError('Original error message')
File "example.py", line 15, in <module>
raise ValueError('Original error message') from e
ValueError: 'Original error message'from zombie import ExceptionTransformation, Reraise transforms = [ ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, error_message='A KeyError occurred', raise_from_error=True, ), ExceptionTransformation( original_exception=TypeError, new_exception=RuntimeError, error_message='A TypeError occurred', raise_from_error=True, ), ] # Using as a decorator with multiple transforms @Reraise(transforms) def func(): raise KeyError('Original error message') func()
Traceback (most recent call last):
File "example.py", line 20, in <module>
func()
File "example.py", line 15, in func
raise KeyError('Original error message')
KeyError: 'Original error message'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "example.py", line 20, in <module>
func()
File "example.py", line 15, in func
raise ValueError('A KeyError occurred') from e
ValueError: A KeyError occurredThe order in which ExceptionTransformation objects are provided to the Reraise context manager or decorator matters.
The transformations are applied sequentially, and the first matching transformation will be used to transform and
raise the exception. This means that if multiple transformations could apply to the same exception,
the first one in the list will take precedence. For example, consider the following transformations:
from zombie import ExceptionTransformation, Reraise # Order matters: The first matching transformation will be applied @Reraise( [ ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, error_message='A KeyError occurred', ), ExceptionTransformation( original_exception=Exception, new_exception=KeyboardInterrupt, error_message='An Exception occurred', ), ] ) def func(): raise KeyError('Original error message') func() # Raises ValueError with message 'A KeyError occurred' # Since KeyError is a subclass of Exception, the second transformation will not be applied.
Traceback (most recent call last): File "zombie.py", line 314, in <module> func() File "zombie.py", line 213, in wrapper _raise_transformed_exception( File "zombie.py", line 138, in _raise_transformed_exception _transform_and_raise(transform=transform, error=error) File "zombie.py", line 109, in _transform_and_raise raise transform.new_exception(error_message) from None ValueError: A KeyError occurred
In this example, even though KeyError is a subclass of Exception, the ExceptionTransformation for Exception will be applied first, transforming the KeyError into a KeyboardInterrupt. If the order were reversed, the KeyError would be transformed into a RuntimeError instead. Therefore, the order of transformations can affect the final exception that is raised.
ExceptionTransformationerror_messageThe error_message parameter allows you to customize the error message of
the new exception. You can use a static string or a string.Template to
include dynamic content from the original exception. Using the default None will use the original exception's
message.
If the error_message parameter is not provided, the new exception will use the original exception's message.
from zombie import ExceptionTransformation, Reraise # Define an exception transformation without an error message transform = ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, raise_from_error=True ) @Reraise(transform) def example_function(): raise KeyError("Original error message") try: example_function() except Exception as e: print(e) # Output: Original error message
from zombie.zombie import ExceptionTransformation, Reraise # Define an exception transformation with a static error message transform = ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, error_message="A static error message", raise_from_error=True ) @Reraise(transform) def example_function(): raise KeyError("Original error message") try: example_function() except Exception as e: print(e) # Output: A static error message
from zombie import ExceptionTransformation, Reraise import string # Define an exception transformation with a dynamic error message transform = ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, error_message=string.Template("Error: ${original_error_message}"), raise_from_error=True ) @Reraise(transform) def example_function(): raise KeyError("Original error message") try: example_function() except Exception as e: print(e) # Output: Error: Original error message
raise_from_errorThe raise_from_error parameter determines whether the new exception should be
chained from the original exception. If raise_from_error is True,
the new exception will include the original exception as its cause.
False will raise the new exception without the original exception as its cause.
False is the default value.
raise_from_error=Truefrom zombie.zombie import ExceptionTransformation, Reraise # Define an exception transformation with raise_from_error=True transform = ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, error_message="An error occurred", raise_from_error=True ) @Reraise(transform) def example_function(): raise KeyError("Original error message") example_function()
$ python example.py
Traceback (most recent call last):
File "example.py", line 20, in <module>
raise KeyError('Original error message')
KeyError: 'Original error message'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "example.py", line 20, in <module>
raise KeyError('Original error message')
File "example.py", line 15, in <module>
raise ValueError('A KeyError occurred') from e
ValueError: A KeyError occurredraise_from_error=False (default)from zombie import ExceptionTransformation, Reraise # Define an exception transformation with raise_from_error=False transform = ExceptionTransformation( original_exception=KeyError, new_exception=ValueError, error_message="An error occurred", raise_from_error=False ) @Reraise(transform) def example_function(): raise KeyError("Original error message") example_function()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<path_to_project>/zombie/zombie.py", line 146, in wrapper
_raise_transformed_exception(*exception_transformations, error=error)
File "<path_to_project>/zombie/zombie.py", line 116, in _raise_transformed_exception
_transform_and_raise(transform=transform, error=error)
File "<path_to_project>/zombie/zombie.py", line 85, in _transform_and_raise
raise transform.new_exception(error_message) from None
ValueError: An error occurredOwner
Contributors
Categories
Products
AppDynamicsProgramming Languages
PythonLicense
Code Exchange Community
Get help, share code, and collaborate with other developers in the Code Exchange community.View Community