挑选一个类定义

时间:2010-04-13 02:39:10

标签: python pickle

有没有办法挑选一个类定义?

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

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

3 个答案:

答案 0 :(得分:2)

唉,不是直接的。您可以发送class语句的字符串形式或字节码形式,并在接收端使用exec“重新水合”它。

答案 1 :(得分:2)

如果使用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

所以这不是&#34;完美&#34; (或者可能不是预期的那样)......但它确实为动态构建的方法及其依赖性序列化了代码。你只是没有完成课程的其余部分 - 但在这种情况下不需要课程的其余部分。

如果你想得到所有东西,你可以腌制整个会话。

>>> 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

最后,如果您希望运输完成&#34;透明地,你可以使用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上的本地计算机...但是如果您使用远程计算机名称和端口(或者也是如此),那么你就是&#39 ; ll开火到远程机器 - &#34;毫不费力地&#34;。

在此处获取dillpathosppfthttps://github.com/uqfoundation

答案 2 :(得分:1)

该文档很好地解释了哪些可以和不可以被腌制,以及为什么会这样。

http://docs.python.org/library/pickle.html#what-can-be-pickled-and-unpickled

基本上,如果类或模块在被取消标记时可以通过名称导入,它应该可以工作,除非您计划在现在和解开它之间更改类定义。在下面的类定义中,只会选择类名“Test”和方法名称“mymethod”。如果您挑选出类定义,那么更改定义以便attr是一个不同的值,而mymethod会做一些完全不同的事情,pickle会选择新的定义。

class Test(object):
    attr = 5

    def mymethod(self, arg):
        return arg
相关问题