Правильный способ очистки временной папки в классе Python

Я создаю класс, в котором я хочу создать временную рабочую область папок, которые будут сохраняться в течение жизни объекта, а затем будут удалены. Я через tempfile.mkdtemp () в def init чтобы создать пространство, но я прочитал, что я не могу положиться на del называют.

Я хотел что-то вроде этого:

class MyClass:
  def __init__(self):
    self.tempfolder = tempfile.mkdtemp()

  def ... #other stuff

  def __del__(self):
    if os.path.exists(self.tempfolder): shutil.rmtree(self.tempfolder)

есть ли другой/лучший способ справиться с этой? Я читал о "С", но, похоже, только будьте полезны в рамках функции.

4 ответов


предостережение: вы никогда не сможете гарантия что папка temp будет удалена, потому что пользователь всегда может жестко убить ваш процесс, а затем он не может запустить что-либо еще.

что сказал, делать

temp_dir = tempfile.mkdtemp()
try:
    <some code>
finally:
    shutil.rmtree(temp_dir)

поскольку это очень распространенная операция, Python имеет специальный способ инкапсуляции "сделать что-то, выполнить код, очистить": a контекст менеджер. Вы можете написать свой собственный следующим образом:

@contextlib.contextmanager
def make_temp_directory():
    temp_dir = tempfile.mkdtemp()
    try:
        yield temp_dir
    finally:
        shutil.rmtree(temp_dir)

и использовать его as

with make_temp_directory() as temp_dir:
    <some code>

(обратите внимание, что это использует @contextlib.contextmanager ярлык для создания контекстного менеджера. Если вы хотите реализовать один оригинальный способ, вам нужно сделать пользовательский класс с __enter__ и __exit__ методами;__enter__ создаст и вернет каталог temp и __exit__ удалить.


хороший способ справиться с временными файлами и папки через контекстное менеджера. Вот как вы можете использовать tempfile.TemporaryFile или tempfile.NamedTemporaryFile -- как только вы выйдете из with оператор (через обычный выход, возврат, исключение или что-либо еще) файл/каталог и его содержимое будут удалены из файловой системы.

для Python 3.2+, это как tempfile.TemporaryDirectory:

import tempfile

with tempfile.TemporaryDirectory() as temp_dir:
    ... do stuff ...

для более ранних версий Python вы можете легко создать свой собственный контекст менеджера, чтобы сделать то же самое. Различия здесь от ответа @katrielalex-это передача args в mkdtemp() и блок try / finally, чтобы убедиться, что каталог очищается, если возникает исключение.

import contextlib
import shutil

@contextlib.contextmanager
def temporary_directory(*args, **kwargs):
    d = tempfile.mkdtemp(*args, **kwargs)
    try:
        yield d
    finally:
        shutil.rmtree(d)


# use it
with temporary_directory() as temp_dir:
    ... do stuff ...

обратите внимание, что если ваш процесс жестко убили (например. kill -9) тогда каталоги не будут очищаться.


Как заявил Bluewind вы должны убедиться, что обернуть часть yield context manager внутри оператора try: finally, иначе любые исключения на самом деле не будут правильно обработаны внутри context manager.

с Python 2.7 docs

в точке выхода генератора выполняется блок, вложенный в оператор with. После выхода блока генератор возобновляется. Если необработанный исключение происходит в блоке, оно перепрофилируется внутри генератора в точке, где произошел выход. Таким образом, вы можете попробовать...кроме...наконец, оператор для ловушки ошибки (если таковой имеется) или обеспечения некоторой очистки. Если исключение попадает в ловушку только для того, чтобы зарегистрировать его или выполнить какое-либо действие (а не подавить его полностью), генератор должен перезапустить это исключение. В противном случае диспетчер контекста генератора укажет оператору with, что исключение обработано, и выполнение возобновится с помощью оператора сразу после оператора with.

также, если вы используете Python 3.2+, вы должны проверить этот маленький драгоценный камень который имеет все выше завернутые красиво для вас

tempfile.TemporaryDirectory (суффикс=", префикс='tmp', dir=нет)

эта функция создает временный каталог с помощью mkdtemp() (предоставленные аргументы передаются непосредственно базовому каталогу функция.) Результирующий объект можно использовать в качестве менеджера контекста (см. с менеджерами контекста оператора). По завершении контекста (или уничтожения объекта временного каталога) вновь созданный временный каталог и все его содержимое удаляются из файловой системы.

имя каталога можно получить из атрибута name возвращаемого объекта.

каталог можно явно очистить, вызвав метод cleanup ().

новое в версии 3.2.


другая альтернатива с помощью contextlib - сделать ваш объект закрываемым и использовать closing контекст менеджер.

class MyClass:
    def __init__(self):
        self.tempfolder = tempfile.mkdtemp()

    def do_stuff():
        pass

    def close(self):
        if os.path.exists(self.tempfolder):
            shutil.rmtree(self.tempfolder)

затем с помощью контекстного менеджера:

from contextlib import closing

with closing(MyClass()) as my_object:
    my_object.do_stuff()