在CentOS上,pandas.algos._return_false导致dill.dump_session出现PicklingError
我有一个代码框架,用来处理会话数据,使用的是dill这个库。之前一切都运行得很好,直到我开始用pandas这个库。下面的代码在CentOS 6.5上会出现一个叫做PicklingError的错误:
import pandas
import dill
dill.dump_session('x.dat')
问题似乎出在pandas.algos上。实际上,只要运行下面这行代码就能重现这个错误:
import pandas.algos
import dill
dill.dump_session('x.dat') / dill.dumps(pandas.algos)
错误信息是 pickle.PicklingError: Can't pickle <cyfunction lambda1 at 0x1df3050>: it's not found as pandas.algos.lambda1
。
奇怪的是,我的电脑上并没有出现这个错误。我的电脑和CentOS上的pandas(0.14.1)、dill(0.2.1)和python(2.7.6)的版本都是一样的。
查看坏对象时,我得到了:
>>> dill.detect.badobjects(pandas.algos, depth = 1)
{'__builtins__': <module '__builtin__' (built-in)>,
'_return_true': <cyfunction lambda2 at 0x1484d70>,
'np': <module 'numpy' from '/usr/local/lib/python2.7/site-packages/numpy-1.8.2-py2.7-linux-x86_64.egg/numpy/__init__.pyc'>,
'_return_false': <cyfunction lambda1 at 0x1484cc8>,
'lib': <module 'pandas.lib' from '/home/talkr/.local/lib/python2.7/site-packages/pandas/lib.so'>}
这似乎是因为两个操作系统对 pandas.algos
的处理方式不同(可能是因为使用了不同的编译器?)。在我的电脑上,运行 dump_session
没有错误时, pandas.algos._return_false
是 <cyfunction <lambda> at 0x06DD02A0>
,而在CentOS上则是 <cyfunction lambda1 at 0x1df3050>
。为什么会有这样的不同处理呢?
1 个回答
我在Mac上看到的和你不一样。使用同样版本的pandas
,我看到的是这个。我注意到你用的dill
版本不同。我用的是从GitHub上下载的版本。我会检查一下dill
在保存模块或全局变量时是否有改动,这可能会影响某些系统。
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas
>>> import dill
>>> dill.detect.trace(True)
>>> dill.dump_session('x.pkl')
M1: <module '__main__' (built-in)>
F2: <function _import_module at 0x1069ff140>
D2: <dict object at 0x106a0b280>
M2: <module 'dill' from '/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.2.dev-py2.7.egg/dill/__init__.pyc'>
M2: <module 'pandas' from '/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas/__init__.pyc'>
这是我在pandas.algos
中得到的结果,
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas.algos
>>> import dill
>>> dill.dumps(pandas.algos)
'\x80\x02cdill.dill\n_import_module\nq\x00U\x0cpandas.algosq\x01\x85q\x02Rq\x03.'
这是我在pandas.algos._return_false
中得到的结果:
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> import pandas.algos
>>> dill.dumps(pandas.algos._return_false)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.2.dev-py2.7.egg/dill/dill.py", line 180, in dumps
dump(obj, file, protocol, byref, file_mode, safeio)
File "/Users/mmckerns/lib/python2.7/site-packages/dill-0.2.2.dev-py2.7.egg/dill/dill.py", line 173, in dump
pik.dump(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
self.save(obj)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 317, in save
self.save_global(obj, rv)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 748, in save_global
(obj, module, name))
pickle.PicklingError: Can't pickle <cyfunction lambda1 at 0x10d403cc8>: it's not found as pandas.algos.lambda1
所以,现在我可以重现你的错误了。
根据它的构建方式,这看起来是一个无法被序列化的对象。不过,它应该可以在模块内部被序列化……对我来说是这样的。你似乎找到了你在CentOS上看到的pandas
构建对象之间的区别。
查看pandas
的代码库,pandas.algos
是一个pyx
文件……所以这是cython
的内容。这里是代码。
_return_false = lambda self, other: False
如果这是一个.py
文件,我知道它会被序列化。我不知道dill
是如何处理cython
生成的lambda表达式的……(例如,一个lambdacyfunction
)。
看起来有一个提交记录(https://github.com/pydata/pandas/commit/73c71dfca10012e25c829930508b5d6f7ccad5ff),在这个提交中,_return_false
被移到了类外,进入了模块范围。你在CentOS和你的电脑上都能看到这个吗?可能是不同系统的v0.14.1版本在不同的git版本上稍有不同……这取决于你是如何安装pandas
的。
所以显然,我可以通过尝试获取对象的源代码来获取lambda1
……对于lambda来说,如果无法获取源代码,dill
会通过名称来获取……显然它的名字是lambda1
……尽管在.pyx
文件中没有显示。也许这与cython
构建lambda的方式有关。
Python 2.7.8 (default, Jul 13 2014, 02:29:54)
[GCC 4.2.1 Compatible Apple Clang 4.1 ((tags/Apple/clang-421.11.66))] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pandas.algos
>>> import dill
>>> dill.source.importable(pandas.algos._return_false)
'from pandas import lambda1\n'
这个区别可能来自cython
……因为代码是从pandas
中的.pyx
文件生成的。你的cython
版本是什么?我的版本是0.20.2。