python - namedtemporaryfile - tempfile ruby
Manera correcta de limpiar una carpeta temporal en la clase Python (4)
Advertencia: nunca puede garantizar que la carpeta temporal se eliminará, ya que el usuario siempre puede detener el proceso y no puede ejecutar nada más.
Dicho esto, hacer
temp_dir = tempfile.mkdtemp()
try:
<some code>
finally:
shutil.rmtree(temp_dir)
Dado que esta es una operación muy común, Python tiene una manera especial de encapsular "hacer algo, ejecutar código, limpiar": un administrador de contexto . Puedes escribir el tuyo de la siguiente manera:
@contextlib.contextmanager
def make_temp_directory():
temp_dir = tempfile.mkdtemp()
try:
yield temp_dir
finally:
shutil.rmtree(temp_dir)
y usarlo como
with make_temp_directory() as temp_dir:
<some code>
(Tenga en cuenta que esto utiliza el @contextlib.contextmanager
directo @contextlib.contextmanager
para crear un administrador de contexto. Si desea implementar uno de la manera original, debe crear una clase personalizada con los métodos __enter__
y __exit__
; el __enter__
crearía y devolvería el directorio temporal y el __exit__
eliminarlo.
Estoy creando una clase en la que quiero generar un espacio de trabajo temporal de carpetas que persistirán durante la vida útil del objeto y luego se eliminarán. Estoy usando tempfile.mkdtemp () en la definición de inicio para crear el espacio, pero he leído que no puedo confiar en que se llame a.
Estoy queriendo algo como esto:
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)
¿Hay otra / mejor manera de manejar esta limpieza? Estaba leyendo sobre ''con'' pero parece que solo es útil dentro de una función.
Como lo indicó Bluewind , debe asegurarse de envolver la parte de rendimiento del administrador de contexto dentro de un intento: finalmente, de lo contrario, las excepciones no se manejarán correctamente dentro del administrador de contexto.
Desde Python 2.7 documentos
En el punto donde el generador cede, se ejecuta el bloque anidado en la instrucción with. El generador se reanuda después de salir del bloque. Si se produce una excepción no controlada en el bloque, se vuelve a cargar dentro del generador en el punto donde ocurrió el rendimiento. Por lo tanto, puede usar una sentencia try ... except ... finally para interceptar el error (si existe), o asegurarse de que se realice una limpieza. Si se atrapa una excepción simplemente para registrarla o realizar alguna acción (en lugar de suprimirla por completo), el generador debe volver a generar esa excepción. De lo contrario, el administrador de contexto del generador indicará a la instrucción with que la excepción se ha manejado, y la ejecución se reanudará con la instrucción inmediatamente después de la instrucción with.
Además, si estás usando Python 3.2+, deberías ver esta pequeña joya que tiene todo lo anterior bien envuelto para ti.
tempfile.TemporaryDirectory (sufijo = '''', prefijo = ''tmp'', dir = Ninguno)
Esta función crea un directorio temporal utilizando mkdtemp () (los argumentos proporcionados se pasan directamente a la función subyacente). El objeto resultante se puede utilizar como administrador de contexto (consulte Con administradores de contexto de instrucciones). Al completar el contexto (o la destrucción del objeto de directorio temporal), el directorio temporal recién creado y todo su contenido se eliminan del sistema de archivos.
El nombre del directorio se puede recuperar del atributo de nombre del objeto devuelto.
El directorio se puede limpiar explícitamente llamando al método cleanup ().
Nuevo en la versión 3.2.
Otra alternativa que usa contextlib
es hacer que su objeto se pueda cerrar y usar el administrador de contexto de 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)
Luego con el gestor de contexto:
from contextlib import closing
with closing(MyClass()) as my_object:
my_object.do_stuff()
Una buena manera de lidiar con archivos y directorios temporales es a través de un administrador de contexto. Así es como puede usar tempfile.TemporaryFile o tempfile.NamedTemporaryFile : una vez que haya salido de la declaración with
(mediante la salida normal, el retorno, la excepción o cualquier otra cosa), el archivo / directorio y su contenido se eliminarán del sistema de archivos.
Para Python 3.2+, esto está incorporado como tempfile.TemporaryDirectory :
import tempfile
with tempfile.TemporaryDirectory() as temp_dir:
... do stuff ...
Para versiones anteriores de Python, puede crear fácilmente su propio administrador de contexto para hacer exactamente lo mismo. Las diferencias aquí de la respuesta de @katrielalex son el paso de args a mkdtemp()
y el bloque try / finally para asegurarse de que el directorio se limpie si se produce una excepción.
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 ...
Tenga en cuenta que si su proceso es difícil de kill -9
(por ejemplo, kill -9
), los directorios no se limpiarán.