zipfile 将最后几行从我的文件中删除 - 为什么?

问题描述 投票:0回答:3

所以我在 Python 中使用

zipfile
模块时遇到问题。目前,当我尝试压缩 KML 文件以创建新的 KMZ 文件时,我缺少最后几行。 KML 有多长似乎并不重要。我认为这是因为 zipfile 没有写入最后一个压缩块。

kmz = zipfile.ZipFile(kmzPath , 'w')
kmz.write(kmlPath, 'CORS.kml', zipfile.ZIP_DEFLATED)

是的,在你问之前我已经导入了zlib来进行压缩。我也尝试过在较低级别使用 zlib 但遇到同样的问题。我被困住了。

有什么想法吗?

python kml python-2.6 kmz python-zipfile
3个回答
3
投票

确保您已致电

kmz.close()

.write(...)
命令之后,否则文件的完整内容将不会刷新到磁盘。为了确保这种情况自动发生,请始终使用
with
上下文管理器,因为退出循环时文件将被关闭:

with zipfile.ZipFile(kmzPath, 'w') as kmz:
    kmz.write(kmlPath, 'CORS.kml', zipfile.ZIP_DEFLATED)

0
投票

这只是一个猜测,但根据

zipfile
文档:

在退出程序之前,您必须致电

close()
,否则不会写入重要记录。

您没有表明您实际上是在打电话

kmz.close()
- 这可能是问题所在吗?


0
投票

我刚刚为此感到相当头痛。我认为 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
© www.soinside.com 2019 - 2024. All rights reserved.