簡體   English   中英

適用於Python3.6的Zipfile模塊:寫字節而不是Odoo文件

[英]Zipfile module for Python3.6: write to Bytes instead of Files for Odoo


我一直在嘗試使用適用於Python 3.6的zipfile模塊來創建一個包含多個對象的.zip文件。
我的問題是,我必須管理僅允許我使用bytes對象而不是文件的Odoo數據庫中的文件。

這是我當前的代碼:

import zipfile

empty_zip_data = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
zip = zipfile.ZipFile(empty_zip_data, 'w')

# files is a list of tuples: [(u'file_name', b'file_data'), ...]
for file in files:
    file_name = file[0]
    file_data = file[1]
    zip.writestr(file_name, file_data)

哪個返回此錯誤:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/zipfile.py", line 1658, in writestr
  with self.open(zinfo, mode='w') as dest:
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/zipfile.py", line 1355, in open
  return self._open_to_write(zinfo, force_zip64=force_zip64)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/zipfile.py", line 1468, in _open_to_write
  self.fp.write(zinfo.FileHeader(zip64))
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/zipfile.py", line 723, in write
  n = self.fp.write(data)
AttributeError: 'bytes' object has no attribute 'write'

我應該怎么做? 我遵循了ZipFile.writestr()docs ,但是這使我無處可...

編輯:使用file_data = file[1].decode('utf-8')作為第二個參數也沒有用,我得到同樣的錯誤。

如我的評論中所述,問題在於以下這一行:

empty_zip_data = b'PK\x05\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
zip = zipfile.ZipFile(empty_zip_data, 'w')

您正在嘗試將byte對象傳遞到ZipFile()方法中,但是像open()它期望使用類似路徑的對象。

在您的情況下,您可能想利用tempfile模塊(在此特定示例中,我們將從以下相關問題中使用SpooledTemporaryFile

import tempfile
import zipfile

# Create a virtual temp file
with tempfile.SpooledTemporaryFile() as tp:

    # pass the temp file for zip File to open
    with zipfile.ZipFile(tp, 'w') as zip:
        files = [(u'file_name', b'file_data'), (u'file_name2', b'file_data2'),]
        for file in files:
            file_name = file[0]
            file_data = file[1]
            zip.writestr(file_name, file_data)

    # Reset the cursor back to beginning of the temp file
    tp.seek(0)
    zipped_bytes = tp.read()

zipped_bytes
# b'PK\x03\x04\x14\x00\x00\x00\x00\x00\xa8U ... \x00\x00'

請注意使用上下文管理器來確保所有文件對象在加載后都正確關閉。

這為您提供了zipped_bytes ,這是您要傳遞回Odoo的字節。 您還可以通過將zipped_bytes寫入物理文件來測試它的zipped_bytes ,從而對其進行測試:

with open('test.zip', 'wb') as zf:
    zf.write(zipped_bytes)

如果要處理的文件太大,請確保注意並使用文檔中max_size參數。

如果要在沒有臨時文件的情況下處理內存中的所有這些,則可以使用io.BytesIO作為ZipFile的文件對象:

import io
from zipfile import ZIP_DEFLATED, ZipFile

file = io.BytesIO()
with ZipFile(file, 'w', ZIP_DEFLATED) as zip_file:
    for name, content in [
        ('file.dat', b'data'), ('another_file.dat', b'more data')
    ]:
        zip_file.writestr(name, content)

zip_data = file.getvalue()
print(zip_data)

您可能還需要設置如圖所示的壓縮算法,因為否則將使用默認值(不壓縮!)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM