Cython Pickling in Package “not found as” Error

匆匆过客 提交于 2019-12-04 09:45:01

The problem was in the build script. The Pickle module uses the __module__ attribute of a function/class for pickling. That __module__ attribute comes from the first argument to the Extension() constructor in the setup.py script. Since I defined my constructor to be Extension('reduce', ['reduce.pyx']), the __module__ attribute is reduce. It should be bar/reduce though since it's now in a package.

Making setup.py look like:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension('bar/reduce', ['reduce.pyx'])]
)

solves the problem.

EDIT

maybe something like this is possible: Foo.__module__ = 'bar.reduce' in bar/__init__.py

Or you can use the module copyreg. Here are some snippets from the code of copyreg:

"""Helper to provide extensibility for pickle.

This is only useful to add pickle support for extension types defined in
C, not for instances of user-defined classes.
"""

def pickle(ob_type, pickle_function, constructor_ob=None):
    # ...

# Example: provide pickling support for complex numbers.

try:
    complex
except NameError:
    pass
else:

    def pickle_complex(c):
        return complex, (c.real, c.imag)

    pickle(complex, pickle_complex, complex)

OLD VERSION

Pickle does this:

    try:
        __import__(module, level=0)
        mod = sys.modules[module]
        klass = getattr(mod, name)
    except (ImportError, KeyError, AttributeError):
        raise PicklingError(
            "Can't pickle %r: it's not found as %s.%s" %
            (obj, module, name))

Can you try out which line fails?

When pickle piclkes classes and functions like module.function it reasssures itself that this is the right function meant:

# module.py
def function(): # 1
    pass
a = function
def function(): # 2
    pass

Function 1 in a can not be pickled but function 2 can be pickled because it is found in the module under the __name__ it has which is "function".

So in your case pickle does not find the same class Foo in the reduce module as is passed as argument. The argument Foo claims to be found in the module reduce.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!