2016-08-25 3 views
5

私はモジュール/クラスが入ったzipファイルを内部に持っています。私はこのファイルを読んでバイナリ( "rb")を読んでメモリに保存します。どのように私はメモリ内のこのzipファイルを取って、そこからモジュールをロードするでしょう。私はこのためにインポートフックを書く必要がありますか?バイナリのzipデータをメモリから単に実行することはできません。メモリからのモジュールを持つpythonロードzip

これはpython2.7によって自動的に行われるため、ディスク上のプレーンなzipファイルからモジュールをロードするだけで簡単です。しかし、私は、これがメモリ経由で可能かどうかを知りたい

更新: ジップをディスクからインポートすることについて多くの人が言及しています。問題は、私がメモリではないディスクからzipをインポートしたいということです。私は明らかにそれをディスクからバイト単位でメモリに読み込みます。私はzipファイルを構成するメモリ内からこれらのバイトをすべて取り出して、通常のインポートとして使用したいと思います。

+0

:1は、この操作を行う必要があるだろう

はメモリから直接読み取ることがメモリ内のデータをテキスト文字列として読み込むために 'exec'を得ることができます。なぜそれが動作しないのか分かりません。例:http://stackoverflow.com/questions/436198/what-is-an-alternative-to-execfile-in-python-3-0 – daveydave400

+0

しかし、メモリ内のファイルの場合は実際のコードではありませんバイナリデータ(zipファイル自体)を実行しています。私の理解を深めるために、execはコードや文字列でのみ動作します。 – efel

+0

ああ、メモリに保存されているバイナリのZIPデータはまだ圧縮されていますか?私はあなたの質問のポイントは、あなたがそれを解凍する必要がないことだと思いますか?または、少なくとも自分で解凍しないでください。私の次のステップは、圧縮された卵のためにsetuptools/distutilsを見ていると思う。 – daveydave400

答えて

3

EDIT:

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

試験データ(と思う)すべてのために働くことなzipimporterを修正

__init__.py内容:

def test(): 
    print("Test") 

test_submodule.py内容:

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

(Macの場合)テストジップを作成します:inmem_zip_importer.py

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

特別ジップインポート:

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 
を10

使用:

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) 
+0

これは楽しいでした。私は前にこのような何かをしたことがないが、Googleは助けた。 zipfileモジュールが存在していることを示すために@junfengshouに感謝します。 – daveydave400

+0

また、 'zipimport'パッケージがありますが、オープンファイルオブジェクト(https://docs.python.org/2/library/zipimport.html)で動作するとは思われません。 – daveydave400

+0

ああ、とても良い答えです。私はあなたがどのようにモジュールインポートフックを作ったのが大好きです。すごい仕事!私はコメントを追加したいと思います。ここでは、zipファイルをメモリから直接読み込むのではなく、ディスクから読み込みます。メモリ内から直接読み込むには、バイナリの全内容を変数に読み込み、IO objバイトで格納する必要があります: http://stackoverflow.com/questions/2463770/python-in-memory-zip-library また、開かれた後にファイルを閉じて、実際にメモリから来ているかどうかテストするファイルの名前を変更してください。 この回答を解決策としてマークしてください。もう一度偉大な仕事! – efel

-2

は(解凍またはディスクへの書き込みは行わない)ジップからのtest.txtをお読みください。

のpython 3(あなたがpy2.xを使用している場合、あなたはPY2にPY3のzip APIを変更する必要があります)

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()) 
+2

これは質問に答えません – user2682863

関連する問題