【问题标题】:pandas.algos._return_false causes PicklingError with dill.dump_session on CentOSpandas.algos._return_false 在 CentOS 上使用 dill.dump_session 导致 PicklingError
【发布时间】:2014-08-26 14:29:30
【问题描述】:

我有一个代码框架,其中涉及使用 dill 转储会话。这曾经工作得很好,直到我开始使用熊猫。以下代码在 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

问题是,我的电脑上没有出现这个错误。它们都有相同版本的 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 的不同处理(可能是不同的编译器?)。在我的 PC 上,dump_session 没有错误,pandas.algos._return_false&lt;cyfunction &lt;lambda&gt; at 0x06DD02A0&gt;,而在 CentOS 上是 &lt;cyfunction lambda1 at 0x1df3050&gt;。为什么处理方式不同?

【问题讨论】:

  • 您可以尝试查明发生了什么的事情可能是查看 pandas 将什么放入全局命名空间。如果没有,那么我能说的最好的办法就是打开dill.detect.trace(True) 并重试。这至少应该向您展示更多失败期间发生的事情。您还可以尝试使用dill.detect.badobjects 和其他工具来查看导致错误的原因。你知道如何导入 lambda1 吗?如果是这样,那可能会有所帮助。

标签: python python-2.7 pandas pickle dill


【解决方案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

所以,我现在可以重现您的错误。

根据它的构建方式,这看起来像是一个不可拾取的对象。 但是,它应该可以在模块内腌制……就像我一样。您似乎已经确定了您在 Pandas 在 CentOS 上构建的对象中看到的区别。

查看pandas 代码库,pandas.algos 是一个pyx 文件……所以这是cython。 这是代码。

_return_false = lambda self, other: False

如果在.py 文件中,我知道它会序列化。我不知道dill 如何为cython 生成的 lambdas 工作……(例如 lambda cyfunction)。

看起来有一个提交 (https://github.com/pydata/pandas/commit/73c71dfca10012e25c829930508b5d6f7ccad5ff),其中 _return_false 被移出一个类进入模块范围。你在 CentOS 和你的 PC 上都看到了吗?可能是针对不同发行版的 v0.14.1 被切断了略有不同的 git 版本……取决于您安装 pandas 的方式。

显然,我可以通过尝试获取对象的源来获取lambda1……对于 lambda,如果它无法获取源,dill 将按名称获取……显然它被命名为 @ 987654343@… 即使它没有出现在 .pyx 文件中。也许是因为cython 是如何构建 lambdas 的。

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。

【讨论】:

  • 但是我在我的电脑上遇到了同样的错误dill.dumps(pandas.algos._return_false):PicklingError: Can't pickle &lt;cyfunction &lt;lambda&gt; at 0x06DD02A0&gt;: it's not found as pandas.algos.lambda1
  • 问题是……为什么 CentOS 会破解打开 pandas,什么时候它应该只允许 dill 通过引用序列化模块,然后一切正常?
  • 我也不知道为什么 CentOS 正在构建 lambda1 而不是 &lt;lambda&gt;。这可能需要用谷歌搜索一下。
  • 那次提交是从 2012 年开始的,而 2014 年只是几个月前,所以即使两个 0.14.1 版本是从不同的提交中删除的(即一个不是来自标签的),它们肯定仍然是有那个。无论如何都要为侦探工作+1。
  • 问题确实出在 cython 上。有关详细信息,请参阅here。当我设法用新的 cython 重新编译 pandas 的那一刻,问题就解决了。
猜你喜欢
  • 2012-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-26
  • 2016-12-12
相关资源
最近更新 更多