【问题标题】:Zip a directory and delete it right afterwards using shutil压缩目录并在之后使用 shutil 将其删除
【发布时间】:2021-05-01 06:12:49
【问题描述】:

我正在尝试压缩给定目录,然后立即删除该目录。 因此我使用shutil 模块。

我实现的方法如下所示:

def _zip(fulldname, delete_after=False):
"""
Zip a directory

:param dname: The full name of the directory
:type dname: str
:param delete_after: Delete the directory after it has been zipped?
:type delete_after: bool
:return: the full name of the zip file
:rtype: str
"""
if not os.path.isdir(fulldname):
    raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT),
                            fulldname)
fullzipfname = shutil.make_archive(fulldname, "zip", root_dir=fulldname,
                            base_dir="./")
if delete_after:
    shutil.rmtree(fulldname)
return fullzipfname

当我执行它时,我要么收到以下错误,要么该方法永远运行(即卡在 shutil.rmtree() 方法上):

File "/media/sf_projects/robot_framework/rfw_rest_api/src/main/rfw_rest_api/rfw_rest_api.py", line 126, in exec_robot
output_arc = core._zip(proc_output_dir, delete_after=True)
File "/media/sf_projects/robot_framework/rfw_rest_api/src/main/core.py", line 147, in _zip
shutil.rmtree(fulldname)
File "/usr/lib/python3.7/shutil.py", line 498, in rmtree
onerror(os.rmdir, path, sys.exc_info())
File "/usr/lib/python3.7/shutil.py", line 496, in rmtree
os.rmdir(path)
OSError: [Errno 26] Text file busy: '../../output/pcap_based_fuzzer_210127_120207'

我做错了什么?

【问题讨论】:

    标签: python zip archive shutil


    【解决方案1】:

    似乎该程序(或其他进程)正在访问fulldname 目录中的文件,而您正试图删除它。从错误“文本文件忙”判断,该文件很可能是正在执行的二进制文件。我会确保在调用该函数时,该目录中的任何文件都不会在程序中保持打开状态。

    另外,根据docsmake_archivebase_dir参数必须与root_dir参数相关。您确定变量fulldname 及其保存的路径满足此属性吗?

    【讨论】:

    • 1) 尝试删除目录时,如何确保不执行二进制文件?当它试图删除空目录时调用失败,但是当我在目录实际上是空的之后查看它时。 2)也许我理解base_dir错误,但我想这样我会指定压缩目录中所有压缩文件的相对路径是./
    • 必须纠正自己...我的意思是相对路径前缀而不是路径。对于./,我想确保如果我压缩包含文件examplefile 的目录exampledir/,则压缩文件在路径exampledir/examplefile 下包含此文件。
    【解决方案2】:

    我终于找到了完全避免shutil的解决方案:

    def _zip(fulldname, delete_after=False):
    """
    Zip a directory
    
    :param fulldname: The full name of the directory
    :type fulldname: str
    :param delete_after: Delete the directory after it has been zipped?
    :type delete_after: bool
    :return: the name of the zip file
    :rtype: str
    """
    if not os.path.isdir(fulldname):
        raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT),
                                fulldname)
    fullzipfname = fulldname + ".zip"
    with zipfile.ZipFile(fullzipfname, "w", zipfile.ZIP_DEFLATED) as zipf:
        for root, dirs, files in os.walk(fulldname):
            for _dir in dirs:
                zipf.write(os.path.join(root, _dir),
                           os.path.relpath(os.path.join(root, _dir),
                                           os.path.join(fulldname)))
            for file in files:
                zipf.write(os.path.join(root, file),
                           os.path.relpath(os.path.join(root, file),
                                           os.path.join(fulldname)))
    logger.debug(f"Created zip directory {fullzipfname}")
    if delete_after:
        for root, dirs, files in os.walk(fulldname, topdown=False):
            for file in files:
                os.remove(os.path.join(root, file))
            for _dir in dirs:
                os.rmdir(os.path.join(root, _dir))
        os.rmdir(fulldname)
        logger.debug(f"Removed original directory {fulldname}")
    return fullzipfname.split(os.path.sep)[-1]
    

    我还注意到shutilmake_archive 有时会一直运行。 尽管在大多数情况下使用 os.walk()zipfile.ZipFile 并没有明显更快,但它似乎仍然更可靠。

    【讨论】:

      猜你喜欢
      • 2012-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      相关资源
      最近更新 更多