cpython icon indicating copy to clipboard operation
cpython copied to clipboard

Objects referencing private-mangled names do not roundtrip properly under pickling.

Open 379dc349-3a10-424f-b9d2-a0104f092359 opened this issue 7 years ago • 6 comments

BPO 33007
Nosy @avassalotti, @serhiy-storchaka, @anntzer, @MojoVampire, @ZackerySpytz
PRs
  • python/cpython#21480
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2018-03-06.05:36:52.125>
    labels = ['3.8', 'library', '3.9', '3.10']
    title = 'Objects referencing private-mangled names do not roundtrip properly under pickling.'
    updated_at = <Date 2020-07-15.17:51:11.385>
    user = 'https://github.com/anntzer'
    

    bugs.python.org fields:

    activity = <Date 2020-07-15.17:51:11.385>
    actor = 'serhiy.storchaka'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2018-03-06.05:36:52.125>
    creator = 'Antony.Lee'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 33007
    keywords = ['patch']
    message_count = 2.0
    messages = ['313306', '349838']
    nosy_count = 5.0
    nosy_names = ['alexandre.vassalotti', 'serhiy.storchaka', 'Antony.Lee', 'josh.r', 'ZackerySpytz']
    pr_nums = ['21480']
    priority = 'normal'
    resolution = None
    stage = 'patch review'
    status = 'open'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue33007'
    versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']
    

    Linked PRs

    • gh-99669

    Consider the following example:

        import pickle
    
        class T:
            def __init__(self):
                self.attr = self.__foo
    
            def __foo(self):
                pass
    
        print(pickle.loads(pickle.dumps(T())))
    

    This fails on 3.6 with AttributeError: 'T' object has no attribute '__foo' (i.e. there's a lookup on the unmangled name). As a comparison, replacing __foo with _foo results in working code.

    This problem is specific to private methods AFAICT, since they're the only things which have an unmangled __name__ used to pickle them, but are stored as a mangled name.

    More details on cause and solution on issue bpo-37852, which I closed as a duplicate of this issue.

    Having this same issue on Python 3.10. Any updates on this?

    joeyagreco avatar Jul 08 '22 18:07 joeyagreco

    @joeyagreco We have a PR if the author fixes, I can merge after some verification.

    nanjekyejoannah avatar Oct 07 '22 21:10 nanjekyejoannah

    @nanjekyejoannah I have fixed the PR's merge conflicts.

    ZackerySpytz avatar Dec 11 '22 04:12 ZackerySpytz

    Technically, #21480 LGTM. But there is a question -- should we support pickling private methods? They are private for reason -- to prevent the use outside of the class methods. Does pickling and copying fall under this use? For now, when it doesn't work, but you only find out when you try to unpickle it, we're free to solve it one way or another. Either make it officially unsupported and raise an exception when trying to pickle it, or make it working seamlessly like other methods. Note that mangling is an implementation detail of CPython, so there is no guarantee that pickles will be compatible with other Python implementations.

    serhiy-storchaka avatar Jan 03 '26 12:01 serhiy-storchaka

    Since this never worked before, I reclassify this as a new feature.

    #21480 only handles private bound methods. Staticmethods, classmethods and unbound methods are not supported.

    serhiy-storchaka avatar Jan 06 '26 16:01 serhiy-storchaka