2012-10-02 17 views
14

¿Es posible verificar si un archivo se ha eliminado o vuelto a crear en python?Compruebe si se ha eliminado un archivo abierto después de abrirlo en python

Por ejemplo, si realizó open("file") en el script, y luego mientras ese archivo aún está abierto, hace rm file; touch file;, entonces el script aún tendrá una referencia al archivo anterior aunque ya haya sido eliminado.

+0

trabajo tal vez os.path.exists en este caso? – Alex

+2

el problema con os.path.exists es que puede existir otro archivo con el mismo nombre de ruta, aunque el archivo anterior ya se haya eliminado – user1502906

Respuesta

4

Sí. Use the os.stat() function para verificar la longitud del archivo. Si la longitud es cero (o la función devuelve el error "Archivo no encontrado"), alguien borró el archivo.

Como alternativa, puede abrir + escribir + cerrar el archivo cada vez que necesite escribir algo en él. El inconveniente es que abrir un archivo es una operación bastante lenta, por lo que esto es imposible si necesita escribir una gran cantidad de datos.

¿Por qué? Porque el nuevo archivo no es el archivo que mantiene abierto. En pocas palabras, los sistemas de archivos Unix tienen dos niveles. Una es la entrada del directorio (es decir, el nombre del archivo, el tamaño del archivo, la hora de modificación, el puntero a los datos) y el segundo nivel es la información del archivo.

Cuando abre un archivo, Unix usa el nombre para buscar los datos del archivo. Después de eso, opera solo en el segundo nivel: los cambios en la entrada del directorio no tienen efecto en ningún "manejador de archivos" abierto. Que es exactamente por qué puede eliminar la entrada del directorio: su programa no lo está usando.

Cuando usa os.stat(), no vuelve a mirar los datos del archivo sino a la entrada del directorio.

En el lado positivo, esto le permite crear archivos que nadie puede ver más que su programa: abra el archivo, bórrelo y luego úselo. Como no hay entrada de directorio para el archivo, ningún otro programa puede acceder a los datos.

En el lado negativo, no puede resolver fácilmente problemas como el que tiene.

+1

En Linux, puede buscar 'proc//fd/...' y acceder al datos incluso si el archivo fue eliminado. Eso a veces es útil si quieres hacer una copia de un video que estás descargando de youtube ;-) – hochl

+0

gracias, sabía que tendría algo que ver con la estadística – user1502906

+0

@hochl: Interesante. Nota: Para leer el contenido del directorio 'fd' de un proceso, debe ser ese usuario o raíz (los permisos son' dr-x ------ '), por lo que aún es seguro. –

3

Sí, puede usar la instalación inotify para verificar cambios de archivos y más. También hay un Python binding para él. Usando inotify puede ver archivos o directorios para la actividad del sistema de archivos. Del manual de los siguientes eventos pueden ser detectados:

IN_ACCESS   File was accessed (read) (*). 
IN_ATTRIB   Metadata changed, e.g., permissions, timestamps, extended attributes, link count (since Linux 2.6.25), UID, GID, etc. (*). 
IN_CLOSE_WRITE File opened for writing was closed (*). 
IN_CLOSE_NOWRITE File not opened for writing was closed (*). 
IN_CREATE   File/directory created in watched directory (*). 
IN_DELETE   File/directory deleted from watched directory (*). 
IN_DELETE_SELF Watched file/directory was itself deleted. 
IN_MODIFY   File was modified (*). 
IN_MOVE_SELF  Watched file/directory was itself moved. 
IN_MOVED_FROM  File moved out of watched directory (*). 
IN_MOVED_TO  File moved into watched directory (*). 
IN_OPEN   File was opened (*). 

Desde aquí se puede buscar en Google a sí mismo una solución, pero creo que se entiende la idea general. Por supuesto, esto solo puede funcionar en Linux, pero de su pregunta supongo que la está usando (referencias a rm y touch).

14

Debe fstat el descriptor de archivo para el archivo abierto.

>>> import os 
>>> f = open("testdv.py") 
>>> os.fstat(f.fileno()) 
posix.stat_result(st_mode=33188, st_ino=1508053, st_dev=65027L, st_nlink=1, st_uid=1000, st_gid=1000, st_size=1107, st_atime=1349180541, st_mtime=1349180540, st_ctime=1349180540) 
>>> os.fstat(f.fileno()).st_nlink 
1 

Ok, este archivo tiene un enlace, por lo que un nombre en el sistema de archivos. Ahora quitarlo:

>>> os.unlink("testdv.py") 
>>> os.fstat(f.fileno()).st_nlink 
0 

No más enlaces, por lo que tenemos un "archivo anónimo" eso es sólo kept alive as long as we have it open. Creación de un nuevo archivo con el mismo nombre no tiene ningún efecto sobre el antiguo archivo:

>>> g = open("testdv.py", "w") 
>>> os.fstat(g.fileno()).st_nlink 
1 
>>> os.fstat(f.fileno()).st_nlink 
0 

Por supuesto, st_nlink a veces puede ser >1 inicialmente, por lo que la comprobación de que para el cero no es del todo fiable (aunque en un entorno controlado, se podría ser lo suficientemente bueno).En su lugar, puede verificar si el archivo en el camino que abrió inicialmente es el mismo que tiene un descriptor de archivo para comparando stat resultados:

>>> os.stat("testdv.py") == os.fstat(f.fileno()) 
False 
>>> os.stat("testdv.py") == os.fstat(g.fileno()) 
True 

(Y si quieres que esto sea 100% correcto, entonces usted debe comparar sólo los campos st_dev y st_ino en stat resultados, ya que los otros campos y st_atime en particular, podrían cambiar entre las llamadas.)

Cuestiones relacionadas