python - Python3.6 的 Zipfile 模块 : write to Bytes instead of Files for Odoo

标签 python odoo virtual-memory python-zipfile


我一直在尝试使用 Python 3.6 的 zipfile 模块来创建一个包含多个对象的 .zip 文件。
我的问题是,我必须管理 Odoo 数据库中的文件,该数据库只允许我使用 bytes 对象而不是文件。

这是我当前的代码:

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 模块(在这个特定的示例中,我们将使用来自 SpooledTemporaryFilerelevant question :

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 写入物理文件来测试它,首先查看它的外观:

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

如果您正在处理相当大的文件,请务必注意并使用 max_size argument in the documentation.

关于python - Python3.6 的 Zipfile 模块 : write to Bytes instead of Files for Odoo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54200941/

相关文章:

odoo - 预期单例 odoo 9

ios - iOS 上使用 Memory Monitor 时虚拟内存消耗和实际内存的区别

sockets - 是否可以将套接字内存映射到虚拟内存?

c - 在 x64 Ubuntu 14.04 上用另一个页表条目覆盖页表条目

python - django:在添加新照片时删除以前的照片

python - 查看 python 字典的字典中是否存在键列表

python - 使用 Ipython 并行在 PBS 集群上注册超时

python - Python/OpenCV —在两个图像中匹配细菌的质心点

html - 当我使用浏览器刷新页面 (F5) 重新加载页面时,Odoo 状态栏出现故障

python - 安装 Openerp 后创建数据库的问题