压缩目录并在之后使用 shutil 删除它

Zip a directory and delete it right afterwards using shutil

我正在尝试压缩给定目录,然后立即删除该目录。 因此我正在使用 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'

我做错了什么?

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

另外,根据docsmake_archivebase_dir参数必须相对于root_dir参数。你确定变量 fulldname 和它持有的路径满足这个 属性?

我终于找到了一个完全避免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 并没有明显加快,但它似乎仍然更可靠。