Cython Pickling in Package not found as Error

2024/10/10 14:22:46

I'm having trouble pickling a Cython class, but only when it's defined inside a package. This problem was noted previously online, but they didn't state how it was resolved. There are two components here: the Cython pickling using a __reduce__ method and a package error.

Cython Pickling Success

I'll first show how it works without the package part. This example works correctly.

Cython File

My Cython file is reudce.pyx:

cdef class Foo(object):cdef int ndef __init__(self, n):self.n = ndef __reduce__(self):return Foo, (self.n,)

Setup File

This may be compiled with a setup.py:

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_extsetup(cmdclass = {'build_ext': build_ext},ext_modules = [Extension("reduce", ["reduce.pyx"])]
)

by executing python setup.py build && cp build/lib*/reduce.so .

Test Script

The test script is called test_reduce.py and is:

import reduce
import pickle
f = reduce.Foo(4)
print pickle.dumps(f)

Executing python test_reduce.py works fine.

Cython Pickling in Package Failure

However, once the reduce.pyx is put into a package, there is an error.

Package Creation

To reproduce this, first create a package called bar.

mkdir bar
mv reduce.so bar
echo "from reduce import Foo" > bar/__init__.py 

Test Script

Change the test_reduce.py file to be:

import bar
import pickle
f = bar.Foo(4)
print pickle.dumps(f)

Error Message

Running python test_reduce.py gives the following error:

File "/usr/lib/python2.7/pickle.py", line 286, in savef(self, obj) # Call unbound method with explicit self
File "/usr/lib/python2.7/pickle.py", line 748, in save_global(obj, module, name))
pickle.PicklingError: Can't pickle <type 'reduce.Foo'>: it's not found as reduce.Foo

There is a catch of errors which are all turned into a PicklingError in pickle.py After looking at that code, the specific error which is occuring is:

ImportError: No module named reduce

Sanity Test

To check that there is not some kind of scope or other issue, if I run the steps which the pickle module should execute, everything works:

f = bar.Foo(4)
call, args = f.__reduce__()
print call(*args)

So what's going on here?!

Answer

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_extsetup(cmdclass = {'build_ext': build_ext},ext_modules = [Extension('bar/reduce', ['reduce.pyx'])]
)

solves the problem.

https://en.xdnf.cn/q/69887.html

Related Q&A

How can I process images faster with Python?

Id trying to write a script that will detect an RGB value on the screen then click the x,y values. I know how to perform the click but I need to process the image a lot faster than my code below curren…

KFolds Cross Validation vs train_test_split

I just built my first random forest classifier today and I am trying to improve its performance. I was reading about how cross-validation is important to avoid overfitting of data and hence obtain bett…

Using Keras, how can I input an X_train of images (more than a thousand images)?

My application is accident-avoidance car systems using Machine Learning (Convolutional Neural Networks). My images are 200x100 JPG images and the output is an array of 4 elements: the car would move le…

Fastest way to merge two deques

Exist a faster way to merge two deques than this?# a, b are two deques. The maximum length # of a is greater than the current length # of a plus the current length of bwhile len(b):a.append(b.poplef…

Python cannot find shared library in cron

My Python script runs well in the shell. However when I cron it (under my own account) it gives me the following error:/usr/local/bin/python: error while loading shared libraries: libpython2.7.so.1.0: …

Multiple async unit tests fail, but running them one by one will pass

I have two unit tests, if I run them one by one, they pass. If I run them at class level, one pass and the other one fails at response = await ac.post( with the error message: RuntimeError: Event loop…

Pyusb on Windows 7 cannot find any devices

So I installed Pyusb 1.0.0-alpha-1 Under Windows, I cannot get any handles to usb devices.>>> import usb.core >>> print usb.core.find() NoneI do have 1 usb device plugged in(idVendor=…

How to speed up nested for loops in Python

I have the following Python 2.7 code:listOfLists = [] for l1_index, l1 in enumerate(L1):list = []for l2 in L2:for l3_index,l3 in enumerate(L3):if (L4[l2-1] == l3):value = L5[l2-1] * l1[l3_index]list.ap…

Folium Search Plugin No Results for FeatureGroup

Im trying to add search functionality to a map Im generating in Python with Folium. I see there is a handy Search plugin available and able to implement it successfully and get it added to the map. Unf…

writing dictionary of dictionaries to .csv file in a particular format

I am generating a dictionary out of multiple .csv files and it looks like this (example):dtDict = {AV-IM-1-13991730: {6/1/2014 0:10: 0.96,6/1/2014 0:15: 0.92,6/1/2014 0:20: 0.97},AV-IM-1-13991731: {6/1…