所以我在 Python 中使用
zipfile
模块时遇到问题。目前,当我尝试压缩 KML 文件以创建新的 KMZ 文件时,我缺少最后几行。 KML 有多长似乎并不重要。我认为这是因为 zipfile 没有写入最后一个压缩块。
kmz = zipfile.ZipFile(kmzPath , 'w')
kmz.write(kmlPath, 'CORS.kml', zipfile.ZIP_DEFLATED)
是的,在你问之前我已经导入了zlib来进行压缩。我也尝试过在较低级别使用 zlib 但遇到同样的问题。我被困住了。
有什么想法吗?
确保您已致电
kmz.close()
在
.write(...)
命令之后,否则文件的完整内容将不会刷新到磁盘。为了确保这种情况自动发生,请始终使用 with
上下文管理器,因为退出循环时文件将被关闭:
with zipfile.ZipFile(kmzPath, 'w') as kmz:
kmz.write(kmlPath, 'CORS.kml', zipfile.ZIP_DEFLATED)
我刚刚为此感到相当头痛。我认为 zipfile 与“with”一起工作的方式存在错误。
我正在创建一个 zip 文件,其中包含一些文件。然后我就立刻复制了。
我使用了“with”语法,因为这就是文档中的内容。
但是,当我对原始文件和副本进行 cksum 时,它们是不同的,即使副本是在“with”块之外(在它之后)完成的。有时复制的 zip 文件仅包含部分存档文件,有时 zip 文件已损坏。然而,cksum 报告在原始文件上运行,而使用 os.system(f"cksum {file}") 在 python 代码中完成的副本在副本之前和之后是相同的。只有当我在脚本完成后对原始文件与副本进行 cksum 时,原始文件才会包含应有的所有档案,但副本不会。
就像“with”块完成时没有调用 close() 一样,因此文件不会刷新,并且复制会继续复制不完整的存档。我尝试在最后显式关闭 'with' 块内的 zipFile,但是当最终 'with' 块尝试关闭 zipFile 时,会产生错误。
因此,我决定在分叉的子进程中进行压缩,并等待子进程完成,这样,如果“with”zip 关闭逻辑中存在任何错误,则当进程退出时,所有文件都会被刷新。 这有效通过关闭逻辑确认了 zipfile 中的错误。
读完这篇文章后,我放弃了子进程和“with”块。不依赖“with”来为我关闭我的zip文件,而是在没有“with”块的情况下明确地执行它。
因此 zipfile 似乎有一个错误,其中“with”不会关闭/刷新 zip 存档,使其在块结束后打开一段时间。
# This way works
zipped_path=f"/path/to/file.zip"
zipFile = zipfile.ZipFile(f"{zipped_path}",mode=mode,compression=zipfile.ZIP_DEFLATED) # do the same thing without 'with'
for what_to_write in list_of_paths:
zipFile.write(f"{what_to_write.path}",arcname=f"{what_to_write.arcname}")
zipFile.close()
# If I do a copy of the file here, it will be complete
# This way does not work
zipped_path=f"/path/to/file.zip"
with zipfile.ZipFile(f"{zipped_path}",mode=mode,compression=zipfile.ZIP_DEFLATED) as zipFile:
for what_to_write in list_of_paths:
zipFile.write(f"{what_to_write.path}",arcname=f"{what_to_write.arcname}")
# not allowed to do zipFile.close() here or will throw
# already closed error ( as it should )
# If I do a copy of the file here, it might be incomplete because
# zipFile was not closed and flushed when 'with' block ended (bug)
# however if I wrap this in a call to child_pid = os.fork()
# and wait for the subprocess executing the above to end in the parent
# process it works as expected when I do the copy from the parent process
# after waiting for this code to complete in the child process.
# by the time the child process doing the zipping exits, the zip file
# has been flushed/closed properly