python - pickle 类定义

标签 python pickle

有没有办法 pickle 类定义?

我想做的是 pickle 定义(可以动态创建),然后通过 TCP 连接发送它,以便可以在另一端创建一个实例。

我知道可能存在依赖关系,例如该类所依赖的模块和全局变量。我也想在 pickle 过程中捆绑这些,但我不关心自动检测依赖项,因为如果用户有责任指定它们也没关系。

最佳答案

如果您使用 dill,它可以让您将 __main__ 当作一个 python 模块(大部分情况下)。因此,您可以序列化交互式定义的类等。 dill 也(默认情况下)可以将类定义作为 pickle 的一部分进行传输。

>>> class MyTest(object):
...   def foo(self, x):
...     return self.x * x
...   x = 4
... 
>>> f = MyTest() 
>>> import dill
>>>
>>> with open('test.pkl', 'wb') as s:
...   dill.dump(f, s)
... 
>>> 

然后关闭解释器,并通过 TCP 发送文件 test.pkl。在您的远程计算机上,现在您可以获得类实例。

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[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
>>> with open('test.pkl', 'rb') as s:
...   f = dill.load(s)
... 
>>> f
<__main__.MyTest object at 0x1069348d0>
>>> f.x
4
>>> f.foo(2)
8
>>>             

但是如何获取类定义呢?所以这不是你想要的。然而,以下是。

>>> class MyTest2(object):
...   def bar(self, x):
...     return x*x + self.x
...   x = 1
... 
>>> import dill
>>> with open('test2.pkl', 'wb') as s:
...   dill.dump(MyTest2, s)
... 
>>>

然后在发送文件后......你可以得到类定义。

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[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
>>> with open('test2.pkl', 'rb') as s:
...   MyTest2 = dill.load(s)
... 
>>> print dill.source.getsource(MyTest2)
class MyTest2(object):
  def bar(self, x):
    return x*x + self.x
  x = 1

>>> f = MyTest2()
>>> f.x
1
>>> f.bar(4)
17

所以,在 dill 中,有 dill.source,它有方法可以检测函数和类的依赖关系,并将它们与 pickle 一起使用(对于大部分)。

>>> def foo(x):
...   return x*x
... 
>>> class Bar(object):
...   def zap(self, x):
...     return foo(x) * self.x
...   x = 3
... 
>>> print dill.source.importable(Bar.zap, source=True)
def foo(x):
  return x*x
def zap(self, x):
  return foo(x) * self.x

所以这不是“完美的”(或者可能不是预期的)……但它确实序列化了动态构建方法的代码及其依赖项。您只是没有得到类(class)的其余部分——但在这种情况下不需要类(class)的其余部分。

如果你想得到所有的东西,你可以 pickle 整个 session 。

>>> import dill
>>> def foo(x):
...   return x*x
... 
>>> class Blah(object):
...   def bar(self, x):
...     self.x = (lambda x:foo(x)+self.x)(x)
...   x = 2
... 
>>> b = Blah()
>>> b.x
2
>>> b.bar(3)
>>> b.x
11
>>> dill.dump_session('foo.pkl')
>>> 

然后在远程机器上...

Python 2.7.9 (default, Dec 11 2014, 01:21:43) 
[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
>>> dill.load_session('foo.pkl')
>>> b.x
11
>>> b.bar(2)
>>> b.x
15
>>> foo(3)
9

最后,如果您希望透明地为您“完成”传输,您可以使用 pathos.ppppft,它们提供将对象运送到第二个 python 服务器(在远程机器上)或 python 进程。他们在后台使用 dill,并通过网络传递代码。

>>> class More(object):
...   def squared(self, x):
...     return x*x
... 
>>> import pathos
>>> 
>>> p = pathos.pp.ParallelPythonPool(servers=('localhost,1234',))
>>> 
>>> m = More()
>>> p.map(m.squared, range(5))
[0, 1, 4, 9, 16]

servers 参数是可选的,这里只是连接到端口 1234 上的本地机器......但是如果你使用远程机器名称和端口代替(或作为好吧),您将“毫不费力”地启动到远程机器。

在此处获取 dillpathosppft:https://github.com/uqfoundation

关于python - pickle 类定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2626636/

相关文章:

python - 是否可以从具有相同名称的查询字符串中获取值?

python - cPickle - pickle 同一对象的不同结果

Python: pickle 模块的替代方法

python - 在seaborn中绘制单独的组时如何将数据作为一组包含

python - 如何隐藏玩家的输入

python - 将多个 blob 输入到 azure 函数 python 中

python - boost python enable_pickling 期望

python - 使用正则表达式和 pandas 分隔字母和数字

python - pickle cython类

python - 在python中查看pickle文件中的图像