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
复制相似问题