我怀疑这是一个普遍的问题,但尚未找到解决方案。我想要的非常简单,并且在技术上似乎可行:我有一个简单的python类,并且希望将其存储在磁盘,实例和定义的单个文件中。Pickle将存储数据,但不存储类定义。可能有人争辩说,类定义已经存储在我的.py文件中,但是我不想使用单独的.py文件。我的目标是要有一个独立的文件,可以用单行代码弹出到我的命名空间中。
所以是的,我知道可以使用两个文件和两行代码,但是我希望在一个文件和一行代码中实现。原因是因为我经常遇到这种情况。我正在处理一些大型数据集,并在python中进行操作,然后必须将切片,切块和转换后的数据写回到某些预先存在的目录结构中。我不想用乱码的python类存根乱丢这些数据目录,以使我的代码和数据保持关联,而我想要的甚至更少的麻烦是跟踪和组织所有已定义的小类在脚本中独立运行。
因此,便利性不在于代码的可读性,而在于代码与数据之间毫不费力且毫无歧义的关联。对我来说,这似乎是一个值得追求的目标,尽管我知道这在大多数情况下都不适当。
因此问题是:是否存在执行此类操作的软件包或代码片段,因为我似乎找不到任何东西。
如果使用dill,则可以将其__main__视为python模块(大部分情况下)。因此,您可以序列化交互式定义的类等。 dill(默认情况下)也可以将类定义作为pickle的一部分进行传输。
dill
__main__
>>> 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) ... >>>
然后关闭解释器,并test.pkl通过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
由于您正在寻找 一支班轮 ,所以我可以做得更好。我没有显示您可以同时发送类和实例,也许那正是您想要的。
>>> import dill >>> class Foo(object): ... def bar(self, x): ... return x+self.x ... x = 1 ... >>> b = Foo() >>> b.x = 5 >>> >>> with open('blah.pkl', 'wb') as s: ... dill.dump((Foo, b), 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('blah.pkl', 'rb') as s: ... Foo, b = dill.load(s) ... >>> b.x 5 >>> Foo.bar(b, 2) 7
因此,在中dill,有dill.source和,这些方法可以检测函数和类的依赖关系,并将它们与pickle一起使用(大部分情况下)。
dill.source
>>> 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
因此,这并不是“完美的”(或者可能不是预期的)……但是它确实将代码动态化为动态构建方法及其依赖项。您只是没有得到课程的其余部分- 但是在这种情况下,不需要课程的其余部分。尽管如此,它似乎仍不是您想要的。
如果您想获取所有内容,则可以对整个会话进行腌制。并在 一行中 (两列import)。
import
>>> 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 >>> # the one line >>> 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 >>> # the one line >>> dill.load_session('foo.pkl') >>> b.x 11 >>> b.bar(2) >>> b.x 15 >>> foo(3) 9
最后,如果您希望透明地“完成”传输(而不是使用文件),则可以使用pathos.pp或ppft,这提供了将对象运送到第二台python服务器(在远程计算机上)或python进程的功能。他们dill在引擎盖下使用,只是通过电线传递代码。
pathos.pp
ppft
>>> 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……但是,如果您改为(或同时)使用远程计算机名称和端口,则将“轻松”触发远程计算机。
servers
1234
获取dill,pathos以及ppft此处:https : //github.com/uqfoundation
pathos