загрузка python zip с модулями из памяти

Так что скажем, у меня есть zip-файл с модулями / классами внутри. Затем я прочитал этот файл – прочитал двоичный файл («rb»), чтобы сохранить его в памяти. Как я могу взять этот zip-файл в память и загрузить из него модуль. Мне нужно написать для этого крюк импорта? Нельзя просто запустить exec на двоичные данные zip из памяти, не так ли?

Я просто знаю, как просто загрузить модуль из простого zip-файла на диске, поскольку это выполняется автоматически с помощью python2.7. Я, однако; хотите знать, возможно ли это через память.

Обновление: многие люди упоминают об импорте zip с диска. Проблема в том, что я хочу импортировать zip из памяти NOT disk. Я, очевидно, прочитаю его с диска и побайтовый байт. Я хочу взять все эти байты из памяти, которые составляют zip-файл и использовать его как обычный импорт.

EDIT: Исправлено ZipImporter для работы во всем (я думаю)

Данные испытаний:

 mkdir mypkg vim mypkg/__init__.py vim mypkg/test_submodule.py 

__init__.py Содержание:

 def test(): print("Test") 

test_submodule.py Содержимое:

 def test_submodule_func(): print("This is a function") 

Создать тестовый почтовый ящик (на Mac):

 zip -r mypkg.zip mypkg rm -r mypkg # don't want to accidentally load the directory 

Специальный импорт zip в inmem_zip_importer.py :

 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 

Использование:

 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) еще одна вещь …:

Для чтения непосредственно из памяти нужно было бы это сделать:

 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) 

прочитайте test.txt из zip (не разархивируйте или не запишите на диск):

python 3 (если вы используете py2.x, вы должны изменить py3 zip API на py2)

 import zipfile file_rst = [] with zipfile.ZipFile('/test/xxx.zip') as my_zip: with my_zip.open('test.txt') as my_file: for line in my_file: file_rst.append(line.strip())