Traceback serialization library that enables pickling tracebacks and raising exceptions with pickled tracebacks in different processes.
npx @tessl/cli install tessl/pypi-tblib@3.1.0A traceback serialization library that enables pickling tracebacks and raising exceptions with pickled tracebacks in different processes. Ideal for multiprocessing, distributed computing, celery, and any scenario requiring traceback preservation across process boundaries.
pip install tblibfrom tblib import Traceback, Code, Frame, TracebackParseErrorFor pickling support:
from tblib import pickling_supportFor decorators and error handling:
from tblib.decorators import return_error, Error, reraisefrom tblib import Traceback
import pickle
# Serialize a traceback to dictionary (no pickling)
try:
raise ValueError("example error")
except Exception:
import sys
tb = Traceback(sys.exc_info()[2])
dict_repr = tb.as_dict()
# Restore traceback from dictionary
restored_tb = Traceback.from_dict(dict_repr)
traceback_obj = restored_tb.as_traceback()
# Enable pickle support for all exceptions
from tblib import pickling_support
pickling_support.install()Core functionality for serializing and deserializing traceback objects without pickle, using dictionary representations that are JSON-safe.
class Traceback:
def __init__(self, tb, *, get_locals=None):
"""
Wrap builtin traceback objects for serialization.
Parameters:
- tb: builtin traceback object
- get_locals: function that takes frame and returns dict of locals
"""
def as_dict(self):
"""
Convert to dictionary representation with only builtin types.
Returns:
dict: Serializable representation of traceback
"""
def as_traceback(self):
"""
Convert to builtin Traceback object for raising or rendering.
Returns:
traceback: Usable builtin traceback object
"""
@classmethod
def from_dict(cls, dct):
"""
Create instance from dictionary with same structure as as_dict().
Parameters:
- dct: dict, dictionary representation from as_dict()
Returns:
Traceback: New traceback instance
"""
@classmethod
def from_string(cls, string, strict=True):
"""
Create instance by parsing a stacktrace string.
Parameters:
- string: str, stacktrace string to parse
- strict: bool, whether parsing stops at non-indented lines
Returns:
Traceback: New traceback instance
"""
# Aliases for convenience
Traceback.to_dict = Traceback.as_dict
Traceback.to_traceback = Traceback.as_tracebackSupporting classes that replicate builtin frame and code objects for serialization compatibility.
class Frame:
def __init__(self, frame, *, get_locals=None):
"""
Replicate builtin Frame object for serialization.
Parameters:
- frame: builtin frame object
- get_locals: function that takes frame and returns dict of locals
"""
def clear(self):
"""Compatibility method for PyPy 3.5"""
class Code:
def __init__(self, code):
"""
Replicate builtin Code object for serialization.
Parameters:
- code: builtin code object
"""Decorators and utilities for capturing exceptions and their tracebacks in a serializable form.
def return_error(func, exc_type=Exception):
"""
Decorator that catches exceptions and returns Error objects instead.
Parameters:
- func: function to wrap
- exc_type: exception type to catch (default: Exception)
Returns:
function: Wrapped function that returns Error on exception
"""
class Error:
def __init__(self, exc_type, exc_value, traceback):
"""
Wrapper for exceptions with preserved tracebacks.
Parameters:
- exc_type: type of exception
- exc_value: exception instance
- traceback: traceback object
"""
@property
def traceback(self):
"""Get traceback object."""
def reraise(self):
"""Reraise the original exception with traceback."""
def reraise(tp, value, tb=None):
"""
Reraise exception with given traceback (similar to six.reraise).
Parameters:
- tp: exception type
- value: exception instance or None
- tb: traceback object or None
"""
def apply_with_return_error(args):
"""
Apply function with arguments, returning Error on exception.
Parameters:
- args: tuple where first element is callable, rest are arguments
Returns:
Any or Error: Function result or Error instance on exception
"""
# Convenience aliases
returns_error = return_error
return_errors = return_error
returns_errors = return_errorEnable pickle support for tracebacks and exceptions, allowing them to be serialized and deserialized across process boundaries.
def install(*exc_classes_or_instances, get_locals=None):
"""
Install pickle support for tracebacks and exceptions.
Parameters:
- *exc_classes_or_instances: specific exception classes/instances to enable
- get_locals: function to get local variables from frames
Usage:
- install() - enable for all exception types
- install(ValueError, TypeError) - enable for specific types
- Can be used as decorator for exception classes
"""Helper functions for working with local variables and traceback data.
def get_all_locals(frame):
"""
Get all local variables from a frame.
Parameters:
- frame: frame object
Returns:
dict: All local variables in frame
"""class TracebackParseError(Exception):
"""Raised when traceback parsing fails during from_string()."""from tblib import Traceback
import json
try:
1 / 0
except:
import sys
tb = Traceback(sys.exc_info()[2])
# Serialize to JSON-safe dict
tb_dict = tb.as_dict()
json_str = json.dumps(tb_dict)
# Deserialize from dict
restored_dict = json.loads(json_str)
restored_tb = Traceback.from_dict(restored_dict)
usable_tb = restored_tb.as_traceback()from tblib import pickling_support
import pickle
import multiprocessing
# Enable pickle support
pickling_support.install()
def worker():
try:
raise ValueError("Error in worker process")
except Exception as e:
# Exception and traceback can now be pickled
return pickle.dumps(e)
def main():
with multiprocessing.Pool() as pool:
result = pool.apply(worker)
# Unpickle the exception with full traceback
exc = pickle.loads(result)
raise exc # Will show full traceback including worker processfrom tblib import Traceback
def get_safe_locals(frame):
"""Only return simple, serializable locals"""
safe_locals = {}
for key, value in frame.f_locals.items():
if isinstance(value, (str, int, float, bool, type(None))):
safe_locals[key] = value
return safe_locals
try:
local_var = "sensitive_data"
raise ValueError("error")
except:
import sys
tb = Traceback(sys.exc_info()[2], get_locals=get_safe_locals)
tb_dict = tb.as_dict() # Contains only safe local variablesfrom tblib.decorators import return_error, Error
@return_error
def risky_function(x):
if x < 0:
raise ValueError("Negative value not allowed")
return x * 2
# Usage
result = risky_function(-5)
if isinstance(result, Error):
print(f"Error occurred: {result.exc_value}")
result.reraise() # Re-raise with full traceback
else:
print(f"Success: {result}")from tblib import Traceback
# Parse a traceback from string format
stacktrace_text = """
Traceback (most recent call last):
File "script.py", line 10, in main
File "script.py", line 5, in helper
"""
try:
tb = Traceback.from_string(stacktrace_text)
usable_tb = tb.as_traceback()
except TracebackParseError as e:
print(f"Failed to parse traceback: {e}")