実際のディスクファイルを使用せずに、メモリ内のZipアーカイブを操作できるPythonライブラリがありますか?
ZipFileライブラリでは、アーカイブを更新できません。唯一の方法は、それをディレクトリに抽出し、変更を加え、そのディレクトリから新しいZipを作成することです。 Zipアーカイブをダウンロードし、変更を加え、再度アップロードするため、ディスクにアクセスせずにZipアーカイブを変更したいので、保存する理由はありません。
JavaのZipInputStream/ZipOutputStreamに似た何かがトリックを行いますが、ディスクアクセスを回避するインターフェイスはすべて問題ありません。
Pythonドキュメント によると:
class zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])
Open a Zip file, where file can be either a path to a file (a string) or a file-like object.
したがって、メモリ内のファイルを開くには、ファイルのようなオブジェクトを作成するだけです(おそらく BytesIO を使用します)。
file_like_object = io.BytesIO(my_Zip_data)
zipfile_ob = zipfile.ZipFile(file_like_object)
記事から PythonのインメモリZip :
以下は、Pythonでメモリを圧縮することに関する2008年5月の私の投稿で、Posterousがシャットダウンしたために再投稿されました。
私は最近、Pythonでメモリ内のZipファイルに利用可能な有料コンポーネントがあることに気付きました。これは無料であるべきだと考えて、次のコードをまとめました。非常に基本的なテストのみが行われているため、エラーが見つかった場合はお知らせください。更新します。
import zipfile
import StringIO
class InMemoryZip(object):
def __init__(self):
# Create the in-memory file-like object
self.in_memory_Zip = StringIO.StringIO()
def append(self, filename_in_Zip, file_contents):
'''Appends a file with name filename_in_Zip and contents of
file_contents to the in-memory Zip.'''
# Get a handle to the in-memory Zip in append mode
zf = zipfile.ZipFile(self.in_memory_Zip, "a", zipfile.Zip_DEFLATED, False)
# Write the file to the in-memory Zip
zf.writestr(filename_in_Zip, file_contents)
# Mark the files as having been created on Windows so that
# Unix permissions are not inferred as 0000
for zfile in zf.filelist:
zfile.create_system = 0
return self
def read(self):
'''Returns a string with the contents of the in-memory Zip.'''
self.in_memory_Zip.seek(0)
return self.in_memory_Zip.read()
def writetofile(self, filename):
'''Writes the in-memory Zip to a file.'''
f = file(filename, "w")
f.write(self.read())
f.close()
if __== "__main__":
# Run a test
imz = InMemoryZip()
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
imz.writetofile("test.Zip")
エティエが提供した例にはいくつかの問題があり、そのうちのいくつかは重大です。
InMemoryZip
属性として保持できますruamel.std.zipfile
(私は著者です)をインストールすると、更新されたバージョンが利用可能になります。後
pip install ruamel.std.zipfile
または here のクラスのコードを含めると、次のことができます。
import ruamel.std.zipfile as zipfile
# Run a test
zipfile.InMemoryZipFile()
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
imz.writetofile("test.Zip")
または、imz.data
を使用して、必要な場所に内容を書き込むことができます。
with
ステートメントを使用することもできます。ファイル名を指定すると、Zipの内容はそのコンテキストを離れるときに書き込まれます。
with zipfile.InMemoryZipFile('test.Zip') as imz:
imz.append("test.txt", "Another test").append("test2.txt", "Still another")
ディスクへの書き込みが遅延するため、そのコンテキスト内の古いtest.Zip
から実際に読み取ることができます。
import io
import zipfile
Zip_buffer = io.BytesIO()
with zipfile.ZipFile(Zip_buffer, "a", zipfile.Zip_DEFLATED, False) as Zip_file:
for file_name, data in [('1.txt', io.BytesIO(b'111')), ('2.txt', io.BytesIO(b'222'))]:
Zip_file.writestr(file_name, data.getvalue())
with open('C:/1.Zip', 'wb') as f:
f.write(Zip_buffer.getvalue())