Подтвердить что ты не робот

Как удалить каталог, созданный с помощью tempfile.mkdtemp?

У меня есть программа на Python, которая создает временные каталоги в /temp с помощью tempfile.mkdtemp. К сожалению, программа Python не удалила каталог после его использования. Так что теперь на диске мало места.

Вопросы:

  1. Как удалить временные каталоги, оставленные в /temp вручную? Я пытался удалить их вручную, но получил сообщение об ошибке "Отказано в доступе".
  2. В программе Python, как удалить каталог temp после их использования?
4b9b3361

Ответ 1

Для управления ресурсами (например, файлами) в Python рекомендуется использовать ключевое слово with, которое автоматически освобождает ресурсы (т.е. Очищает, как закрытие файлов); это доступно из Python 2.5.

Из Python 3.2, вы можете использовать tempfile.TemporaryDirectory() вместо tempfile.mkdtmp() - это использовать в with и автоматически очищает каталог:

from tempfile import TemporaryDirectory

with TemporaryDirectory() as temp_dir:
    # ... do something with temp_dir
# automatically cleaned up when context exited

Если вы используете более раннюю версию Python (по крайней мере, 2.5, то есть with), вы можете использовать backports.tempfile; см. Николас Бишопс ответ на tempfile.TeventDirectory контекстный менеджер в Python 2.7.

Легко и поучительно накатить свой собственный класс, называемый контекстным менеджером. Возвращаемое значение метода __enter__() привязано к цели предложения as, в то время как метод __exit__() вызывается при выходе из контекста - даже по исключению - и выполнении очистки.

import shutil
import tempfile

class TemporaryDirectory(object):
    """Context manager for tempfile.mkdtemp() so it usable with "with" statement."""
    def __enter__(self):
        self.name = tempfile.mkdtemp()
        return self.name

    def __exit__(self, exc_type, exc_value, traceback):
        shutil.rmtree(self.name)

Вы можете упростить это с @contextlib.contextmanager декоратора @contextlib.contextmanager, поэтому вам не нужно писать менеджер контекста вручную. Код перед yield выполняется при входе в контекст, полученное значение привязывается к цели as, а код после yield выполняется при выходе из контекста. По сути, это сопрограмма, которая заключает в себе получение и освобождение ресурса, а выход yield к управлению набором (телом) предложения with. Обратите внимание, что здесь вам не нужно иметь try...finally -то блокировать, так как @contextlib.contextmanager не перехватывать исключения в yield - это только факторы управления ресурсами в сопрограммы.

from contextlib import contextmanager
import tempfile
import shutil

@contextmanager
def TemporaryDirectory():
    name = tempfile.mkdtemp()
    try:
        yield name
    finally:
        shutil.rmtree(name)

Как просто отмечает Lizl, если вы не возражаете против уже удаляемого каталога (который, как предполагает приведенный выше код, не происходит), вы можете поймать исключение "Нет такого файла или каталога" следующим образом:

import errno
# ...
try:
    shutil.rmtree(self.name)
except OSError as e:
    # Reraise unless ENOENT: No such file or directory
    # (ok if directory has already been deleted)
    if e.errno != errno.ENOENT:
        raise

Вы можете сравнить со стандартной реализацией в tempfile.py; даже этот простой класс имел ошибки и развивался на протяжении многих лет.

Для справки о with, см.:

Ответ 2

Прочитайте документацию , это просто.;) Из документов: каталог доступен для чтения, доступен для записи и доступен для поиска только при создании идентификатора пользователя.

Чтобы удалить каталог temp, попробуйте что-то вроде этого:

import errno
import shutil
import tempfile

try:
    tmp_dir = tempfile.mkdtemp()  # create dir
    # ... do something
finally:
    try:
        shutil.rmtree(tmp_dir)  # delete directory
    except OSError as exc:
        if exc.errno != errno.ENOENT:  # ENOENT - no such file or directory
            raise  # re-raise exception

Также вы можете попробовать tempdir или посмотреть его источники.

Ответ 3

Я думаю, что пользователь несет ответственность за удаление временного каталога и его содержимого, созданного с помощью tempfile.mkdtemp(). он не будет удален автоматически, как временный файл. Есть много способов удалить каталог

Если каталог пуст, вы можете использовать

'os.removedirs or os.rmdir'

Обратите внимание, что его можно использовать только в том случае, если каталог пуст

OSError

Это удалит весь путь к каталогу:

import shutil    
shutil.rmtree('/path/to/your/dir/')

будьте осторожны при использовании этого, он удалит весь каталог и файлы внутри него.

Ответ 4

У меня была такая же/похожая проблема с использованием TemporaryDirectory(), которая в основном охватывает функции, которые вы определили выше.

Моя проблема была из-за использования временного каталога. Раньше я заполнял содержимое путем клонирования репозитория git, случалось, что во время процесса создавались файлы только для чтения, и при обычном выходе эти временные файлы только для чтения приводили к тому, что весь временный каталог оставался там.

Унаследовал ли TemporaryDirectory от моего собственного класса и переопределил метод класса _cleanup с помощью следующего кода.

Код перед super() может быть оптимизирован, но для меня производительность не была проблемой.

Я использовал силу и прочитал источник " tempfile "

import tempfile
import shutil
import stat 

class myTempDir(tempfile.TemporaryDirectory):
    @classmethod
    def _cleanup(self,name, warn_message):
        for root, dirs, files in os.walk(name):
            for fname in files:
                full_path = os.path.join(root, fname)
                os.chmod(full_path ,stat.S_IWRITE)
        super()

Решение работало для Windows 10 с Python 3