Richard Oudkerk added the comment: There is a cute way to use operator.attrgetter to produce backwards compatible pickles using the qualname:
import pickle, copyreg, operator, sys, pickletools, types class AttrGetter(object): def __init__(self, name): self.name = name def __call__(self): # pretend to be callable raise RuntimeError def __reduce__(self): return operator.attrgetter, (self.name,) def reduce_by_qualname(obj): mod = sys.modules[obj.__module__] first, rest = obj.__qualname__.split('.', 1) firstobj = getattr(mod, first) assert operator.attrgetter(rest)(firstobj) is obj return AttrGetter(rest), (firstobj,) # FunctionType defaults to save_global but uses fallback if it fails copyreg.pickle(types.FunctionType, reduce_by_qualname) class A(object): class B(object): class C(object): @staticmethod def foo(): print("foo foo foo") def bar(): print("bar bar bar") for obj in [A.B.C.foo, bar]: data = pickle.dumps(obj, 2) pickletools.dis(data) func = pickle.loads(data) assert func is obj func() This produces 0: \x80 PROTO 2 2: c GLOBAL 'operator attrgetter' 23: q BINPUT 0 25: X BINUNICODE 'B.C.foo' 37: q BINPUT 1 39: \x85 TUPLE1 40: q BINPUT 2 42: R REDUCE 43: q BINPUT 3 45: c GLOBAL '__main__ A' 57: q BINPUT 4 59: \x85 TUPLE1 60: q BINPUT 5 62: R REDUCE 63: q BINPUT 6 65: . STOP highest protocol among opcodes = 2 foo foo foo 0: \x80 PROTO 2 2: c GLOBAL '__main__ bar' 16: q BINPUT 0 18: . STOP highest protocol among opcodes = 2 bar bar bar ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue13520> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com