os.path.existe () las mentiras

Estoy ejecutando varios scripts de Python en un clúster de Linux, y la salida de un trabajo es generalmente la entrada a otro script, que posiblemente se ejecute en otro nodo. Encuentro que hay un cierto retraso no significativo antes de que Python notifique los archivos que se han creado en otros nodos: os.path.exists () también devuelve false y open () también falla. Puedo hacer un bucle mientras no os.path.exists (mypath) hasta que aparezca el archivo, y puede tardar más de un minuto, lo que no es óptimo en una canalización con muchos pasos y, potencialmente, ejecutar muchos conjuntos de datos en paralelo.

La única solución que he encontrado hasta ahora es llamar a subprocess.Popen (“ls% s”% (pathdir), shell = True), que mágicamente soluciona el problema. Me imagino que este es probablemente un problema del sistema, pero ¿de alguna manera Python podría estar causando esto? ¿Algún tipo de caché o algo así? Mi administrador de sistemas no ha sido de mucha ayuda hasta ahora.

os.path.exists() simplemente llama a la función stat() la biblioteca C.

Creo que estás corriendo en un caché en la implementación NFS del kernel. A continuación se muestra un enlace a una página que describe el problema, así como algunos métodos para vaciar el caché.

Manejador de archivos

Los directorios almacenan en caché los nombres de los archivos a los identificadores de archivos. Los problemas más comunes con esto son:

• Tiene un archivo abierto y necesita verificar si el archivo ha sido reemplazado por un archivo más nuevo. Debe vaciar la memoria caché del manejador de archivos del directorio principal antes de que stat () devuelva la información del nuevo archivo y no la del archivo abierto.

◦ En realidad, este caso tiene otro problema: el archivo anterior puede haber sido eliminado y reemplazado por un nuevo archivo, pero ambos archivos pueden tener el mismo inodo. Puede verificar este caso vaciando el caché de atributos del archivo abierto y luego ver si fstat () falla con ESTALE.

• Es necesario comprobar si existe un archivo. Por ejemplo, un archivo de locking. Kernel puede haber almacenado en caché que el archivo no existe, incluso si en realidad lo hace. Debe vaciar la memoria caché del manejador de archivos negativo del directorio principal para ver si el archivo realmente existe.

Algunas formas de vaciar la caché de identificador de archivo:

• Si se modificó el mtime del directorio principal, la caché del identificador de archivos se vacía al vaciar su caché de atributos. Esto debería funcionar bastante bien si el servidor NFS admite resolución de nanosegundos o microsegundos.

• Linux: chown () el directorio a su propietario actual. El caché de identificador de archivo se vacía si la llamada se devuelve correctamente.

• Solaris 9, 10: la única forma es intentar rmdir () el directorio principal. ENOTEMPTY significa que el caché está vaciado. Al intentar rmdir (), el directorio actual falla con EINVAL y no vacía el caché.

• FreeBSD 6.2: la única forma es intentar rmdir () ya sea el directorio principal o el archivo que se encuentra debajo. Los fallos de ENOTEMPTY, ENOTDIR y EACCES significan que la memoria caché se ha vaciado, pero ENOENT no la ha vaciado. FreeBSD no almacena en caché las entradas negativas, por lo que no es necesario vaciarlas.

http://web.archive.org/web/20100912144722/http://www.unixcoding.org/NFSCoding

El problema está relacionado con el hecho de que el proceso de Python se ejecuta en su propio shell. Cuando ejecuta subprocess.Popen(shell=True) está generando un nuevo shell, que está trabajando alrededor del problema que está experimentando.

Python no está causando este problema. Es una combinación de cómo funcionan los listados de directorios y NFS (almacenamiento de archivos) en Linux.