压缩目录,然后立即使用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'

我做错了什么?

我终于找到了一个完全避免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在大多数情况下并没有明显更快,但它似乎更可靠。

似乎这个程序(或另一个进程)正在访问fulldname目录中的文件,而您正在试图删除它。根据错误"文本文件繁忙"判断,所述文件很可能是正在执行的二进制文件。我将确保当函数被调用时,该目录中的文件在程序中没有保持打开状态。

另外,根据文档,make_archivebase_dir参数必须相对于root_dir参数。您确定变量fulldname及其包含的路径满足此属性吗?

最新更新