チケット #43 (new blog)
pythonでメモリ上でzipに書き込む。
| 報告者: | mtamaki | 担当者: | mtamaki |
|---|---|---|---|
| 優先度: | major | マイルストーン: | |
| コンポーネント: | blog | バージョン: | |
| キーワード: | 関係者: |
説明 (最終更新者: mtamaki) (diff)
pythonはzipファイルの読み書きができて便利ですが、メモリ上のファイルオブジェクトをzipファイルに見立てて書き込む機能が標準になかったので書いてみました。 zipfile.ZipFile.writestrが元。
def zip_raw_write(zip_file, zinfo_or_arcname, obj):
"base: zipfile.ZipFile.writestr"
from zipfile import ZipInfo, ZIP_DEFLATED
import time
if not isinstance(zinfo_or_arcname, ZipInfo):
zinfo = ZipInfo(filename=zinfo_or_arcname,
date_time=time.localtime(time.time()))
zinfo.compress_type = zip_file.compression
else:
zinfo = zinfo_or_arcname
zip_file._writecheck(zinfo)
#オブジェクトを読み込む
read_obj = obj.read()
#大きさを調べてセット
zinfo.file_size = obj.tell() # Uncompressed size
import binascii
#CRCをゲット
zinfo.CRC = binascii.crc32(read_obj) # CRC-32 checksum
if zinfo.compress_type == ZIP_DEFLATED:
import zlib
co = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
zlib.DEFLATED, -15)
#圧縮
read_obj = co.compress(read_obj) + co.flush()
#圧縮後のサイズをセット
zinfo.compress_size = len(read_obj) # Compressed size
else:
zinfo.compress_size = zinfo.file_size
zinfo.header_offset = zip_file.fp.tell() # Start of header obj
zip_file.fp.write(zinfo.FileHeader())
zinfo.file_offset = zip_file.fp.tell() # Start of file obj
#書き込み
zip_file.fp.write(read_obj)
if zinfo.flag_bits & 0x08:
# Write CRC and file sizes after the file data
zip_file.fp.write(struct.pack("<lLL", zinfo.CRC, zinfo.compress_size,
zinfo.file_size))
zip_file.filelist.append(zinfo)
zip_file.NameToInfo[zinfo.filename] = zinfo
if __name__ == '__main__':
#zipをメモリ上でごにょごにょする
import zipfile, StringIO
zip_file_obj = StringIO.StringIO()
def zip_create( path_or_obj, mode ):
try:
# zlib がない場合,この呼び出しは失敗して RuntimeError が返る
return zipfile.ZipFile(path_or_obj, mode, zipfile.ZIP_DEFLATED )
except RuntimeError:
# ZIP_STORED (非圧縮) がデフォルトの設定
return zipfile.ZipFile(path_or_obj, mode) #, zipfile.ZIP_STORED)
zip_file = zip_create( zip_file_obj, "w" )
#サンプルとしてこのコード自体をzipに突っ込むために読み込む
script_file_obj = open( __file__, "r" )
script_file_string = script_file_obj.read()
script_file_obj.close()
#名前を変えてzipに突っ込む
zip_file.writestr( "test.py", script_file_string )
zip_file.writestr( "test2.py", script_file_string )
#zipを閉じる
zip_file.close()
#もう一個zipを用意
zip_file_obj2 = StringIO.StringIO()
zip_file2 = zip_create( zip_file_obj2, "w" )
#さっきのzipをもう一個のzipに突っ込む
zip_file_obj.seek(0,0)
zip_raw_write( zip_file2, "test.zip", zip_file_obj )
zip_file_obj.seek(0,0)
zip_raw_write( zip_file2, "test2.zip", zip_file_obj )
#zipを閉じる
zip_file2.close()
#ファイルに書き出す。
import os
real_zip_file_obj2 = open( os.path.splitext( __file__ )[0] + ".zip", "wb" )
real_zip_file_obj2.write( zip_file_obj2.getvalue() )
real_zip_file_obj2.close()
上記をtest.pyとして実行すると
- test.zip
- test.zip
- test.py
- test2.py
- test2.zip
- test.py
- test2.py
- test.zip
という構造のzipができます。
(080620追記:Python2.5でzip_raw_writeがエラーになります。 PythonZipOnMemory にあるzip_raw_writeと差し替えてください。)
チケットの履歴
Note: チケットについてのヘルプは
TracTickets を参照
して下さい。