所以假设我有一个包含模块/类的zip文件.然后我读了这个文件 – 读取二进制文件(“rb”)将其存储到内存中.我如何将此zip文件存入内存并从中加载模块.我需要为此编写一个导入钩子吗?一个人不能简单地从内存中运行exec二进制zip数据,可以吗?
我知道从磁盘上的普通zip文件加载模块很简单,因为这是由python2.7自动完成的.然而,我;想知道这是否可以通过记忆.
更新:
很多人都提到从磁盘导入zip.问题是我想从内存NOT磁盘导入zip.我显然会逐字节地将它从磁盘读入内存.我想从构成zip文件的内存中获取所有这些字节,并将其用作常规导入.
最佳答案
编辑:修正ZipImporter适用于所有事情(我认为)
测试数据:
@H_502_17@mkdir mypkg vim mypkg/__init__.py vim mypkg/test_submodule.py
__init__.py内容:
@H_502_17@def test(): print("Test")
test_submodule.py内容:
@H_502_17@def test_submodule_func(): print("This is a function")
创建测试Zip(在mac上):
@H_502_17@zip -r mypkg.zip mypkg rm -r mypkg # don't want to accidentally load the directory
inmem_zip_importer.py中的特殊zip导入:
@H_502_17@import os import imp import zipfile class ZipImporter(object): def __init__(self,zip_file): self.z = zip_file self.zfile = zipfile.ZipFile(self.z) self._paths = [x.filename for x in self.zfile.filelist] def _mod_to_paths(self,fullname): # get the python module name py_filename = fullname.replace(".",os.sep) + ".py" # get the filename if it is a package/subpackage py_package = fullname.replace(".",os.sep,fullname.count(".") - 1) + "/__init__.py" if py_filename in self._paths: return py_filename elif py_package in self._paths: return py_package else: return None def find_module(self,fullname,path): if self._mod_to_paths(fullname) is not None: return self return None def load_module(self,fullname): filename = self._mod_to_paths(fullname) if not filename in self._paths: raise ImportError(fullname) new_module = imp.new_module(fullname) exec self.zfile.open(filename,'r').read() in new_module.__dict__ new_module.__file__ = filename new_module.__loader__ = self if filename.endswith("__init__.py"): new_module.__path__ = [] new_module.__package__ = fullname else: new_module.__package__ = fullname.rpartition('.')[0] return new_module
使用:
@H_502_17@In [1]: from inmem_zip_importer import ZipImporter In [2]: sys.Meta_path.append(ZipImporter(open("mypkg.zip","rb"))) In [3]: from mypkg import test In [4]: test() Test function In [5]: from mypkg.test_submodule import test_submodule_func In [6]: test_submodule_func() This is a function
(来自efel)还有一件事……:
要直接从内存中读取,需要执行以下操作:
@H_502_17@f = open("mypkg.zip","rb") # read binary data we are now in memory data = f.read() f.close() #important! close the file! we are now in memory # at this point we can essentially delete the actual on disk zip file # convert in memory bytes to file like object zipbytes = io.BytesIO(data) zipfile.ZipFile(zipbytes)