This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author sbt
Recipients alexandre.vassalotti, lukasz.langa, pitrou, sbt, vstinner
Date 2012-08-21.23:16:03
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1345590964.14.0.139572634752.issue13520@psf.upfronthosting.co.za>
In-reply-to
Content
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
History
Date User Action Args
2012-08-21 23:16:04sbtsetrecipients: + sbt, pitrou, vstinner, alexandre.vassalotti, lukasz.langa
2012-08-21 23:16:04sbtsetmessageid: <1345590964.14.0.139572634752.issue13520@psf.upfronthosting.co.za>
2012-08-21 23:16:03sbtlinkissue13520 messages
2012-08-21 23:16:03sbtcreate