import io
import zipfile
def right():
file = io.BytesIO()
zipfile.ZipFile(file, "w").writestr("test.txt", "test string")
file.seek(0)
zipfile.ZipFile(file, "r")
def wrong():
file = io.BytesIO()
zipping_file = zipfile.ZipFile(file, "w")
zipping_file.writestr("test.txt", "test string")
file.seek(0)
zipfile.ZipFile(file, "r")
right()
print("right ok")
wrong() # BadZipFile Error here!!
print("wrong ok")
我已经在python3.9和3.7.9上试过了。我不明白为什么right()
函数没有抛出它。这两种方法绝对没有区别,不是吗?
发布于 2021-03-17 13:18:50
对于right()
,在发生writestr()
的行之后没有对第一个ZipFile
实例的引用,因此有资格立即完成(calling __del__
, which in turn calls close()
when that wasn't done already)。(Zip文件在文件末尾有一个页脚,用于维护指向其内容的指针;在关闭操作期间更新此索引是典型的)。请注意,Python语言规范并不强制实现垃圾--在删除最后一个引用时立即收集和完成对象,因此一些Python实现可以选择推迟--它不能保证在所有可能的语言实现上以您想要的方式运行,如果您检查了Jython/PyPy/IronPython/等等,就有可能出现错误行为。
使用wrong()
,因为有一个引用,所以zipping_file
无法最终完成,因此在函数结束之前隐式关闭,因此它永远不会编写它的页脚。
只需执行一个显式的close()
来修复这个问题:
def formerly_wrong():
file = io.BytesIO()
zipping_file = zipfile.ZipFile(file, "w")
zipping_file.writestr("test.txt", "test string")
zipping_file.close()
file.seek(0)
zipfile.ZipFile(file, "r")
https://stackoverflow.com/questions/66673656
复制相似问题