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

时间:2015-08-18 14:23:35

标签: 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)

要清楚这只是一个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'

2 个答案:

答案 0 :(得分:45)

ZipFile将其数据写为字节,而不是字符串。这意味着您必须在Python 3上使用BytesIO而不是StringIO

字节和字符串之间的区别在Python 3中是新的。six兼容性库具有Python 2的BytesIO类,如果您希望程序与两者兼容。

答案 1 :(得分:9)

问题是io.StringIO()在需要用作io.BytesIO时被用作内存缓冲区。之所以发生该错误,是因为当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)