Ada*_*erg 10 python serialization pickle
我已经为我们在工作场所内部开发/使用的以流程为中心的作业分发系统编写了一个Python接口.虽然技术娴熟的程序员,使用此界面的主要人员是研究科学家,而不是软件开发人员,因此易于使用并尽可能地保持界面不受影响是至关重要的.
我的库将一系列输入展开到共享文件服务器上的一系列pickle文件中,然后生成加载这些输入,执行计算,pickle结果和退出的作业; 然后客户端脚本选择备份并生成一个生成器,该生成器加载并生成结果(或重新生成计算函数所执行的任何异常.)
这只是有用的,因为计算函数本身就是序列化输入之一.cPickle非常满足于pickle函数引用,但要求pickle函数在相同的上下文中可重新导入.这是有问题的.我已经解决了找到重新导入模块的问题,但绝大多数时候,它是一个顶级函数被腌制,因此没有模块路径.我发现能够在计算节点上取消这样一个函数的唯一策略是这种令人作呕的小方法,用于模拟在取消函数之前对函数进行pickle的原始环境:
...
# At this point, we've identified the source of the target function.
# A string by its name lives in "modname".
# In the real code, there is significant try/except work here.
targetModule = __import__(modname)
globalRef = globals()
for thingie in dir(targetModule):
if thingie not in globalRef:
globalRef[thingie] = targetModule.__dict__[thingie]
# sys.argv[2]: the path to the pickle file common to all jobs, which contains
# any data in common to all invocations of the target function, then the
# target function itself
commonFile = open(sys.argv[2], "rb")
commonUnpickle = cPickle.Unpickler(commonFile)
commonData = commonUnpickle.load()
# the actual function unpack I'm having trouble with:
doIt = commonUnpickle.load()
Run Code Online (Sandbox Code Playgroud)
最后一行是这里最重要的一行 - 我的模块正在拾取它应该实际运行的功能.编写的代码按预期工作,但直接操作符号表是不安的.
我怎么能这样做,或者非常像这样的事情,不会迫使研究科学家将他们的计算脚本分成适当的类结构(他们使用Python就像有史以来最优秀的图形计算器一样,我想继续让他们做那么,Pickle迫切想要的方式,没有我上面使用的令人不快,不安全,只是简单的可怕__dict__和globals()操纵?我热切地相信必须有一个更好的方法,但exec "from {0} import *".format("modname")没有做到,几次尝试将腌渍负荷注入targetModule参考没有做到,并eval("commonUnpickle.load()", targetModule.__dict__, locals())没有做到这一点.所有这些都因Unpickle AttributeError无法找到该功能而失败<module>.
什么是更好的方法?
对于要被识别为已加载的模块,我认为它必须在 sys.modules 中,而不仅仅是将其内容导入到全局/本地命名空间中。尝试执行所有内容,然后从人工环境中获取结果。
env = {"fn": sys.argv[2]}
code = """\
import %s # maybe more
import cPickle
commonFile = open(fn, "rb")
commonUnpickle = cPickle.Unpickler(commonFile)
commonData = commonUnpickle.load()
doIt = commonUnpickle.load()
"""
exec code in env
return env["doIt"]
Run Code Online (Sandbox Code Playgroud)