Shutil.rmtree: примеры (PYTHON)
shutil.rmtree(path: str): NoneОписание функции shutil.rmtree
shutil.rmtree()
рекурсивно удаляет целое дерево каталогов, включая все подкаталоги и файлы. Функция используется, когда требуется полностью удалить директорию со всем её содержимым.path - путь к удаляемой директории. Может быть строкой или объектом, поддерживающим интерфейс os.PathLike. Это обязательный параметр.
ignore_errors - булевый флаг (по умолчанию False). Если установлен в True, ошибки, возникающие в результате неудачного удаления, игнорируются. При значении False ошибки обрабатываются обработчиком onerror.
onerror - функция обратного вызова для обработки ошибок (по умолчанию None). Функция принимает три аргумента: function, path и excinfo. function - функция, вызвавшая ошибку (os.rmdir или os.remove), path - путь к файлу или директории, вызвавшей ошибку, excinfo - информация об исключении, возвращаемая sys.exc_info().
onexc - альтернатива onerror, появившаяся в Python 3.12. Принимает те же аргументы, но вместо вызова через exc_info получает экземпляр исключения. Если указан onexc, параметр onerror игнорируется.
dir_fd - необязательный дескриптор файла, ссылающийся на директорию.
Функция не возвращает никакого значения. В случае успеха директория и все её содержимое удаляются. При возникновении ошибок и ignore_errors=False вызывается обработчик onerror/onexc или исключение.
Базовые примеры использования
Простое удаление директории:
import shutil
shutil.rmtree('/tmp/test_directory')# Директория /tmp/test_directory и всё её содержимое удалены.
Удаление с игнорированием ошибок:
import shutil
shutil.rmtree('/несуществующий/путь', ignore_errors=True)
print('Продолжаем работу')# Не вызовет исключения, даже если путь не существует. Продолжаем работу
Использование обработчика ошибок onerror:
import shutil, os
def error_handler(func, path, exc_info):
print(f'Ошибка при вызове {func.__name__} для пути {path}: {exc_info[1]}')
shutil.rmtree('/защищенная/директория', onerror=error_handler)Ошибка при вызове rmdir для пути /защищенная/директория: [Errno 13] Permission denied: '/защищенная/директория'
Похожие функции в Python
os.remove() и os.unlink() удаляют один файл, но не директории.
os.rmdir() удаляет пустую директорию. Вызывает ошибку, если директория не пуста.
pathlib.Path.unlink() удаляет файл, на который указывает путь. Метод pathlib.Path.rmdir() удаляет пустую директорию. Для рекурсивного удаления можно использовать shutil.rmtree() с объектом Path, преобразованным в строку, или написать собственный рекурсивный метод.
Выбор инструмента зависит от задачи: для одиночных файлов - os.remove, для пустых папок - os.rmdir, для рекурсивного удаления дерева каталогов - shutil.rmtree.
Альтернативы в других языках программирования
PHP: Функция rmdir удаляет только пустые директории. Для рекурсивного удаления нужно создавать свою функцию или использовать RecursiveDirectoryIterator.
function rmdir_recursive($dir) {
foreach(scandir($dir) as $file) {
if ('.' === $file || '..' === $file) continue;
$path = $dir.'/'.$file;
if (is_dir($path)) rmdir_recursive($path);
else unlink($path);
}
rmdir($dir);
}
rmdir_recursive('testdir');JavaScript (Node.js): Модуль fs предоставляет fs.rmSync с опцией { recursive: true }.
const fs = require('fs');
fs.rmSync('./testdir', { recursive: true, force: true });Java: Класс Files имеет метод walkFileTree для обхода дерева файлов и последующего удаления.
Path dir = Paths.get("testdir");
Files.walk(dir)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);C#: Directory.Delete имеет перегрузку с параметром recursive.
System.IO.Directory.Delete("testdir", true);Go: Пакет os.RemoveAll удаляет путь и любые дочерние элементы.
import "os"
err := os.RemoveAll("testdir")Типичные ошибки
PermissionError: Попытка удаления файлов или директорий без достаточных прав.
import shutil
shutil.rmtree('/root/important')PermissionError: [Errno 13] Permission denied: '/root/important'
FileNotFoundError: Указанный путь не существует, а ignore_errors=False.
import shutil
shutil.rmtree('несуществующая_папка')FileNotFoundError: [Errno 2] No such file or directory: 'несуществующая_папка'
OSError: Может возникать по разным причинам, например, когда файл используется другим процессом в Windows.
Удаление символьных ссылок: По умолчанию shutil.rmtree удаляет содержимое директории, на которую указывает символьная ссылка, но не саму ссылку в каталоге, где она находится. Это может привести к неожиданной потере данных, если ссылка указывает на важную директорию вне целевого пути.
Изменения в последних версиях
Python 3.12: Добавлен параметр onexc как замена onerror. Функция onexc принимает те же аргументы, но в качестве третьего аргумента передается экземпляр исключения, а не кортеж exc_info. Если указан onexc, параметр onerror игнорируется.
Python 3.8: Добавлен параметр dir_fd. Изменено поведение onerror: если функция, переданная в onerror, выбрасывает исключение, это исключение теперь не перехватывается.
Расширенные примеры
Использование onexc (Python 3.12+):
import shutil
def onerror_handler(func, path, exc):
print(f'Ошибка {exc} в {func} для {path}')
shutil.rmtree('test_dir', onexc=onerror_handler)Логирование удаляемых файлов:
import shutil, os
def logging_handler(func, path, exc_info):
with open('deletion_log.txt', 'a') as f:
f.write(f'Не удалось удалить {path}: {exc_info[1]}\n')
shutil.rmtree('large_dir', onerror=logging_handler)Безопасное удаление с проверкой:
import shutil, os
def safe_remove_top_level_dir(dir_path):
abs_path = os.path.abspath(dir_path)
# Предотвращаем попытку удаления корневых или системных путей
if abs_path in ['/', '/home', '/etc'] or abs_path.startswith('/sys'):
raise ValueError(f'Попытка удаления защищенного пути: {abs_path}')
shutil.rmtree(abs_path)
safe_remove_top_level_dir('./user_data')Удаление с предварительным выводом списка файлов:
import shutil, os
for root, dirs, files in os.walk('target_dir'):
for file in files:
print(os.path.join(root, file))
confirm = input('Удалить все эти файлы? (y/n): ')
if confirm.lower() == 'y':
shutil.rmtree('target_dir')Использование с pathlib:
from pathlib import Path
import shutil
dir_path = Path('my_directory')
shutil.rmtree(str(dir_path)) # Или shutil.rmtree(dir_path)Обработка ошибок с разными типами исключений:
import shutil, os, stat
def handle_remove_readonly(func, path, exc):
os.chmod(path, stat.S_IWRITE)
func(path)
shutil.rmtree('readonly_dir', onerror=handle_remove_readonly)