Rya*_* R. 15 python function pickle
作为这个问题的后续问题: 是否有一种简单的方法来挑选python函数(或以其他方式序列化其代码)?
我想从上面的帖子中看到这个子弹的一个例子:
"如果函数引用了你需要选择的全局变量(包括导入的模块,其他函数等),你也需要对它们进行序列化,或者在远程端重新创建它们.我的例子只是给它了远程进程的全局命名空间. "
我有一个简单的测试,我正在使用marshal将函数字节代码写入文件:
def g(self,blah):
print blah
def f(self):
for i in range(1,5):
print 'some function f'
g('some string used by g')
data = marshal.dumps(f.func_code)
file = open('/tmp/f2.txt', 'w')
file.write(data)
Run Code Online (Sandbox Code Playgroud)
然后我开始一个新的python实例:
file = open('/tmp/f2.txt', 'r')
code = marshal.loads(file.read())
func2 = types.FunctionType(code, globals(), "some_func_name");
func2('blah')
Run Code Online (Sandbox Code Playgroud)
这导致:
NameError: global name 'g' is not defined
Run Code Online (Sandbox Code Playgroud)
这与我所采用的不同方法无关.我尝试了基本相同的方法来发送g作为f但f仍然看不到g.如何进入全局命名空间,以便f在接收过程中可以使用它?
有人还建议将pyro作为如何执行此操作的示例.我已经尝试了解迪斯科项目中的相关代码.我拿了他们的dPickle类并尝试在独立应用程序中重新创建他们的disco/tests/test_pickle.py功能但没有成功.我的实验在使用转储调用执行函数编组时遇到了问题.无论如何,也许接下来就是热探索.
总之,我所遵循的基本功能是能够通过线路发送方法并将所有基本的"工作空间"方法与其一起发送(如g).
来自答案的更改示例:
工作函数编写者:
import marshal, types
def g(blah):
print blah
def f():
for i in range(1,5):
print 'some function f'
g('blah string used by g')
f_data = marshal.dumps(f.func_code)
g_data = marshal.dumps(g.func_code);
f_file = open('/tmp/f.txt', 'w')
f_file.write(f_data)
g_file = open('/tmp/g.txt', 'w')
g_file.write(g_data)
Run Code Online (Sandbox Code Playgroud)
工作function_reader:
import marshal, types
f_file = open('/tmp/f.txt', 'r')
g_file = open('/tmp/g.txt', 'r')
f_code = marshal.loads(f_file.read())
g_code = marshal.loads(g_file.read())
f = types.FunctionType(f_code, globals(), 'f');
g = types.FunctionType(g_code, globals(), 'g');
f()
Run Code Online (Sandbox Code Playgroud)
ste*_*egt 21
云包执行此操作 - 只需'pip install cloud'然后:
import cloud, pickle
def foo(x):
return x*3
def bar(z):
return foo(z)+1
x = cloud.serialization.cloudpickle.dumps(bar)
del foo
del bar
f = pickle.loads(x)
print f(3) # displays "10"
Run Code Online (Sandbox Code Playgroud)
换句话说,只需要调用cloudpickle.dump()或cloudpickle.dumps(),你会用泡菜一样.*,然后再使用本机和pickle.load()或pickle.loads()解冻.
Picloud在LGPL下发布了'cloud'python包,其他开源项目已经在使用它(google为"cloudpickle.py"看一些).picloud.com上的文档让您了解这段代码的功能有多强大,以及为什么他们有动力将精力投入到通用代码酸洗工作中 - 他们的整个业务都是围绕它构建的.我们的想法是,如果你有cpu_intensive_function()并希望在亚马逊的EC2网格上运行它,你只需要替换:
cpu_intensive_function(some, args)
Run Code Online (Sandbox Code Playgroud)
有:
cloud.call(cpu_intensive_function, some, args)
Run Code Online (Sandbox Code Playgroud)
后者使用cloudpickle来挑选任何相关代码和数据,将其发送到EC2,运行它,并在调用cloud.result()时将结果返回给您.(以毫秒为单位Picloud票据,它的价格便宜赫克,我用这一切的时候了Monte Carlo模拟和金融时间序列分析,当我需要数百个CPU内核的几秒钟每个.我不能说不够好关于它的事情,我甚至不在那里工作.)
我尝试过使用与发送g相同的方法,但是f仍然看不到g。如何将g放入全局名称空间,以便f在接收过程中可以使用它?
将其分配给全局名称g
。(我看到您正在分配f
给func2
而不是f
。如果您正在使用进行类似的操作g
,那么很清楚为什么f
找不到g
。请记住,名称解析g
是在运行时发生的- 在您调用之前不会查找f
。)
当然,我在猜测,因为您没有显示用于执行此操作的代码。
最好创建一个单独的字典,以用于要取消选择的功能的全局名称空间-沙箱。这样,它们的所有全局变量将与您在其中执行的模块分离。因此,您可以执行以下操作:
sandbox = {}
with open("functions.pickle", "rb") as funcfile:
while True:
try:
code = marshal.load(funcfile)
except EOFError:
break
sandbox[code.co_name] = types.FunctionType(code, sandbox, code.co_name)
Run Code Online (Sandbox Code Playgroud)
在此示例中,我假设您已将所有函数的代码对象一个文件一个文件地放置在另一个文件中,并且在读取它们时,我得到了代码对象的名称并将其用作两个函数对象名称的基础以及存储在沙箱字典中的名称。
在未选取的函数中,沙盒字典就是它们的字典globals()
,因此在内部f()
,它们g
从中获取值sandbox["g"]
。打电话给f
是:sandbox["f"]("blah")
归档时间: |
|
查看次数: |
11214 次 |
最近记录: |