Python 3内存Zipfile错误.字符串参数预期,得到'字节'

pxg*_*pxg 33 python python-3.x

我有以下代码来创建一个内存zip文件,该文件抛出在Python 3中运行的错误.

from io import StringIO
from pprint import pprint
import zipfile


in_memory_data = StringIO()
in_memory_zip = zipfile.ZipFile(
    in_memory_data, "w", zipfile.ZIP_DEFLATED, False)
in_memory_zip.debug = 3

filename_in_zip = 'test_filename.txt'
file_contents = 'asdf'

in_memory_zip.writestr(filename_in_zip, file_contents)
Run Code Online (Sandbox Code Playgroud)

要清楚这只是一个Python 3问题.我可以在Python 2上运行良好的代码.确切地说,我使用的是Python 3.4.3.堆栈跟踪如下:

Traceback (most recent call last):
  File "in_memory_zip_debug.py", line 14, in <module>
    in_memory_zip.writestr(filename_in_zip, file_contents)
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/zipfile.py", line 1453, in writestr
    self.fp.write(zinfo.FileHeader(zip64))
TypeError: string argument expected, got 'bytes'
Exception ignored in: <bound method ZipFile.__del__ of <zipfile.ZipFile object at 0x1006e1ef0>>
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/zipfile.py", line 1466, in __del__
    self.close()
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/zipfile.py", line 1573, in close
    self.fp.write(endrec)
TypeError: string argument expected, got 'bytes'
Run Code Online (Sandbox Code Playgroud)

Wan*_*uta 51

ZipFile将其数据写为字节,而不是字符串.这意味着你必须使用BytesIO而不是StringIOPython 3.

字节和字符串之间的区别在Python 3中是新的.如果您希望程序与两者兼容,则六个兼容库具有BytesIOPython 2 的类.

  • 这很令人困惑,因为来自OP的错误消息意味着完全相反的问题.他提供了一个字符串值,因为错误消息表明的是预期的参数类型. (5认同)

小智 14

问题是io.StringIO()当它需要时被用作内存缓冲区io.BytesIO.发生错误是因为zipfile代码最终调用StringIO().当StringIO需要字符串时,Write()包含字节.

一旦它改为BytesIO(),它的工作原理:

from io import BytesIO
from pprint import pprint
import zipfile


in_memory_data = BytesIO()
in_memory_zip = zipfile.ZipFile(
    in_memory_data, "w", zipfile.ZIP_DEFLATED, False)
in_memory_zip.debug = 3

filename_in_zip = 'test_filename.txt'
file_contents = 'asdf'

in_memory_zip.writestr(filename_in_zip, file_contents)
Run Code Online (Sandbox Code Playgroud)