Skip to content

Instantly share code, notes, and snippets.

@rusek
Last active October 1, 2015 18:14
Show Gist options
  • Save rusek/83d774fa40b257126c77 to your computer and use it in GitHub Desktop.
Save rusek/83d774fa40b257126c77 to your computer and use it in GitHub Desktop.
Stupid way to pickle traceback objects in Python
import sys
import types
def _patched_name(code, name):
# argument order is described in help(types.CodeType)
return types.CodeType(
code.co_argcount,
code.co_nlocals,
code.co_stacksize,
code.co_flags,
code.co_code,
code.co_consts,
code.co_names,
code.co_varnames,
code.co_filename,
name,
code.co_firstlineno,
code.co_lnotab,
code.co_freevars,
code.co_cellvars,
)
def pack(tb):
result = []
while tb is not None:
code = tb.tb_frame.f_code
result.append((code.co_filename, tb.tb_lineno, code.co_name))
tb = tb.tb_next
return result
def unpack(packed):
prev_var = '_e'
globs = {prev_var: ZeroDivisionError}
for i, (filename, lineno, name) in enumerate(reversed(packed)):
this_var = '_%d' % i
eval(compile('%sdef %s(): raise %s()' % ('\n' * (lineno - 1), this_var, prev_var), filename, 'exec'), globs)
prev_var = this_var
func = globs[this_var]
func.func_code = _patched_name(func.func_code, name)
try:
globs[prev_var]()
except ZeroDivisionError:
globs.clear()
return sys.exc_info()[2].tb_next
# import copy_reg
# copy_reg.pickle(types.TracebackType, lambda obj: (unpack, (pack(obj), )))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment