Mat*_*yra 18 python import pickle
我正在尝试将Project A同事构建的项目集成到另一个python项目中.现在这位同事没有在他的代码中使用相对导入,而是完成了
from packageA.moduleA import ClassA
from packageA.moduleA import ClassB
Run Code Online (Sandbox Code Playgroud)
然后腌制课程cPickle.为了整洁,我想隐藏他(Project A)在我的项目中构建的包.然而,这会改变定义的类的路径packageA.没问题,我只是重新定义导入使用
from ..packageA.moduleA import ClassA
from ..packageA.moduleA import ClassB
Run Code Online (Sandbox Code Playgroud)
但是现在unle pickle这些类失败并显示以下消息
with open(fname) as infile: self.clzA = cPickle.load(infile)
ImportError: No module named packageA.moduleA
Run Code Online (Sandbox Code Playgroud)
那么为什么cPickle显然没有看到模块defs.我是否需要添加packageA系统路径的根?这是解决问题的正确方法吗?
该cPickled文件看起来像
ccopy_reg
_reconstructor
p1
(cpackageA.moduleA
ClassA
p2
c__builtin__
object
p3
NtRp4
Run Code Online (Sandbox Code Playgroud)
旧的项目层次结构就是那种
packageA/
__init__.py
moduleA.py
moduleB.py
packageB/
__init__.py
moduleC.py
moduleD.py
Run Code Online (Sandbox Code Playgroud)
我想把所有这些都放进去 WrapperPackage
MyPackage/
.. __init__.py
.. myModuleX.py
.. myModuleY.py
WrapperPackage/
.. __init__.py
.. packageA/
.. __init__.py
.. moduleA.py
.. moduleB.py
.. packageB/
.. __init__.py
.. moduleC.py
.. moduleD.py
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 20
您需要为pickle导入创建一个别名才能工作; 以下__init__.py是WrapperPackage包的文件:
from .packageA import * # Ensures that all the modules have been loaded in their new locations *first*.
from . import packageA # imports WrapperPackage/packageA
import sys
sys.modules['packageA'] = packageA # creates a packageA entry in sys.modules
Run Code Online (Sandbox Code Playgroud)
您可能需要创建其他条目:
sys.modules['packageA.moduleA'] = moduleA
# etc.
Run Code Online (Sandbox Code Playgroud)
现在cPickle时会发现packageA.moduleA,并packageA.moduleB在自己的老位置一次.
您可能希望之后重新编写pickle文件,此时将使用新模块位置.上面创建的其他别名应该确保有问题的模块具有新的位置名称,cPickle以便在再次编写类时获取.
除了@MartinPieters 回答之外,另一种方法是定义类的find_global方法cPickle.Unpickler,或扩展pickle.Unpickler类。
def map_path(mod_name, kls_name):
if mod_name.startswith('packageA'): # catch all old module names
mod = __import__('WrapperPackage.%s'%mod_name, fromlist=[mod_name])
return getattr(mod, kls_name)
else:
mod = __import__(mod_name)
return getattr(mod, kls_name)
import cPickle as pickle
with open('dump.pickle','r') as fh:
unpickler = pickle.Unpickler(fh)
unpickler.find_global = map_path
obj = unpickler.load() # object will now contain the new class path reference
with open('dump-new.pickle','w') as fh:
pickle.dump(obj, fh) # ClassA will now have a new path in 'dump-new'
Run Code Online (Sandbox Code Playgroud)
两个过程的更详细的解释pickle,并cPickle可以发现在这里。