shutil.rmtree
不会在Windows上删除只读文件。是否有Python等效的"rm -rf"? 为什么这么麻烦?
shutil.rmtree
不会在Windows上删除只读文件。是否有Python等效的"rm -rf"? 为什么这么麻烦?
shutil.rmtree
可以传入一个错误处理函数,当删除文件时出现问题时会调用该函数。您可以使用它来强制删除有问题的文件。
灵感来源于http://mail.python.org/pipermail/tutor/2006-June/047551.html和http://techarttiki.blogspot.com/2008/08/read-only-windows-files-with-python.html:
import os
import stat
import shutil
def remove_readonly(func, path, excinfo):
os.chmod(path, stat.S_IWRITE)
func(path)
shutil.rmtree(top, onerror=remove_readonly)
(我还没有测试过那段代码,但它应该足以让您开始)
shutil.rmtree('mypath',onerror = lambda func, path, _: (os.chmod(path, stat.S_IWRITE), func(path)))
。 - Basjignore_errors=True
。 - Ali_Shwin32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL)
rmtree = lambda path: subprocess.check_call(['cmd', '/c', 'rd', '/s', '/q', path])
import os, stat
import shutil
def remove_readonly(func, path, _):
"Clear the readonly bit and reattempt the removal"
os.chmod(path, stat.S_IWRITE)
func(path)
shutil.rmtree(directory, onerror=remove_readonly)
shutil.rmtree 有其局限性。尽管在许多情况下可以使用 shutil.rmtree(),但在某些情况下它无法正常工作。例如,在 Windows 下标记为只读的文件无法通过 shutil.rmtree() 删除。
通过从 PyWin32 导入 win32api 和 win32con 模块,并向 rmgeneric() 函数添加类似于 "win32api.SetFileAttributes(path, win32con.FILE_ATTRIBUTE_NORMAL" 的代码行,即可克服这个障碍。我使用了这种方法来修复 Subversion 1.4 的 hot-backup.py 脚本,使其在 Windows 下运行良好。感谢您提供的这份配方。
我不使用 Windows,因此无法验证其是否有效。
在调用rmtree()
时,我遇到了Python 3.7的这个问题,并通过在退出TemporaryDirectory()
上下文管理器之前显式修复权限来解决它。有关详细信息,请参见akaihola/darker#453。以下是实现的副本:
import os
import sys
from pathlib import Path
from typing import Union
WINDOWS = sys.platform.startswith("win")
def fix_py37_win_tempdir_permissions(dirpath: Union[str, Path]) -> None:
"""Work around a `tempfile` clean-up issue on Windows with Python 3.7
Call this before exiting a ``with TemporaryDirectory():`` block or in teardown for
a Pytest fixture which creates a temporary directory.
See discussion in https://github.com/akaihola/darker/pull/393
Solution borrowed from https://github.com/python/cpython/pull/10320
:param dirpath: The root path of the temporary directory
"""
if not WINDOWS or sys.version_info >= (3, 8):
return
for root, dirs, files in os.walk(dirpath):
for name in dirs + files:
path = os.path.join(root, name)
try:
os.chflags(path, 0) # type: ignore[attr-defined]
except AttributeError:
pass
os.chmod(path, 0o700)
以下是如何在 Pytest 单元测试中或使用 tempfile
创建临时目录的方法:
import pytest
from my_utils import fix_py37_win_tempdir_permissions
@pytest.fixture
def myfixture(tmp_path):
# setup code here
yield tmp_path
fix_py37_win_tempdir_permissions(tmp_path)
def myfunc():
with TemporaryDirectory() as tmpdir:
# work on the temporary directory here
fix_py37_win_tempdir_permissions(tmp_path)