Rob*_*ter 22 python destructor temporary-directory
我正在创建一个类,我想在其中生成一个文件夹的临时工作空间,该文件夹将在对象的生命周期中持续存在,然后被删除.我在def init中使用tempfile.mkdtemp()来创建空间,但我已经读过,我不能依赖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)
Run Code Online (Sandbox Code Playgroud)
有没有其他/更好的方法来处理这种清理?我正在阅读有关'with'但它似乎只对函数有用.
Kat*_*iel 40
警告:你永远不能保证临时文件夹会被删除,因为用户可能总是难以杀死你的进程,然后它就无法运行其他任何东西.
那说,做
temp_dir = tempfile.mkdtemp()
try:
<some code>
finally:
shutil.rmtree(temp_dir)
Run Code Online (Sandbox Code Playgroud)
由于这是一个非常常见的操作,Python有一种特殊的方法来封装"做某事,执行代码,清理":一个上下文管理器.您可以按如下方式编写自己的代码:
@contextlib.contextmanager
def make_temp_directory():
temp_dir = tempfile.mkdtemp()
try:
yield temp_dir
finally:
shutil.rmtree(temp_dir)
Run Code Online (Sandbox Code Playgroud)
并用它作为
with make_temp_directory() as temp_dir:
<some code>
Run Code Online (Sandbox Code Playgroud)
(请注意,这使用@contextlib.contextmanager快捷方式创建上下文管理器.如果要以原始方式实现一个,则需要使用__enter__和__exit__方法__enter__创建自定义类; 将创建并返回临时目录并__exit__删除它.
Wrz*_*mft 12
我对此进行了一些尝试,并且我非常有信心,如果您不能使用上下文管理器,那么截至本文发布的最佳解决方案是:
\nclass MyClass(object):\n def __init__(self):\n self.tempfolder = tempfile.TemporaryDirectory()\n \n \xe2\x80\xa6\n\n def __del__(self):\n self.tempfolder.cleanup()\nRun Code Online (Sandbox Code Playgroud)\n(如果您不能确保被跟注,某些条件__del__可能是合理的。)__init__
现在,除了使用较新的TemporaryDirectory而不是 之外mkdtemp,这与您所做的没有太大不同。为什么我仍然认为这是你能做的最好的事情?好吧,我测试了程序退出和类似的几种场景(全部在 Linux 上)并且:
我找不到临时文件夹未被删除的场景,尽管我希望 Python 可以决定MyClass不再需要相应的实例。自动删除最早会在 Python\xe2\x80\x99s 垃圾收集启发式允许的情况下发生。
您可以使用 \xe2\x80\x9chelp\xe2\x80\x9d 垃圾收集器del myinstance和gc.collect()。请注意,这del只会减少引用计数,因此这并不能确保垃圾收集可以发生并被__del__调用。
如果您确实想确保删除(临时目录),您可以显式调用myinstance.__del__(). 如果你能做到这一点,你也许也可以让MyClass自己成为一个上下文管理器。
临时文件夹持续存在的唯一情况是当我从操作系统 \xe2\x80\x93\xc2\xa0 硬杀 Python 时,在这种情况下,我看不到 Python 中的任何解决方案如何工作。
\natexit(如所建议的,例如,通过这个答案)不会改善这种情况:要么删除发生,无论如何atexit,或者它不会发生,即使有atexit。
rco*_*oup 11
处理临时文件和目录的好方法是通过上下文管理器.这就是你如何使用tempfile.TemporaryFile或tempfile.NamedTemporaryFile - 一旦你退出with语句(通过正常的退出,返回,异常或其他任何东西)文件/目录,它的内容将从文件系统中删除.
对于Python 3.2+,它以tempfile.TemporaryDirectory为内置:
import tempfile
with tempfile.TemporaryDirectory() as temp_dir:
... do stuff ...
Run Code Online (Sandbox Code Playgroud)
对于早期的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 ...
Run Code Online (Sandbox Code Playgroud)
请注意,如果您的进程被硬杀死(例如kill -9),则目录将不会被清除.
另一种替代方法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)
Run Code Online (Sandbox Code Playgroud)
然后使用上下文管理器:
from contextlib import closing
with closing(MyClass()) as my_object:
my_object.do_stuff()
Run Code Online (Sandbox Code Playgroud)