Правильный способ очистки временной папки в классе 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.
в точке выхода генератора выполняется блок, вложенный в оператор 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()