python.multiprocessing y "DIRECTORIO DE FALTAS DE ERROR FATAL (INFADI)"

9

Al intentar hacer multiprocesamiento con arcpy, ocasionalmente me encuentro con este error:

FATAL ERROR (INFADI)
MISSING DIRECTORY

No tengo idea de qué está provocando este error, y bloquea el proceso de Python, por lo que es imposible obtener un rastreo en él. Se produce al escribir la salida de trama final de un modelo de sonido largo.

A veces va acompañado de un error.

Unable to write BND file for %TEMP%\ras####

Donde% Temp se analiza correctamente y #### es un número aleatorio de 4 dígitos. Esto es inusual porque cada proceso tiene su propio espacio de trabajo, que es donde se deben escribir la mayoría de los archivos.

El problema no son los datos de entrada ... Puedo volver a ejecutar el programa en las entradas fallidas y se ejecutará correctamente.

castillo-blord
fuente
Volveré a este pronto, pero tengo que trabajar en un modelo diferente en este momento.
blord-castillo

Respuestas:

6

Aquí hay algunas cosas para verificar:

¿Estás usando cursores? ¿Los estás liberando? ¿Estás tratando de reutilizar algún objeto en diferentes procesos? ¿Estás compartiendo la misma ubicación temporal? ¿Estás haciendo procesamiento de memoria?

En general, el arco es solo una envoltura alrededor de los objetos com y cualquier tipo de multiprocesamiento será complicado.

Jamie
fuente
4

Encontré que este problema surge cuando arcpy.env.workspace y arcpy.env.scratchWorkspace son iguales para dos procesos diferentes. Arc escribe casi todos los rásteres intermedios en el espacio de trabajo (o espacio de trabajo temporal) en el formato ESRI GRID. No puede escribir dos rásteres ESRI GRID en el mismo directorio al mismo tiempo debido a la estructura de pseudo-base de datos del formato (la carpeta de información contiene claves únicas para cada ráster).

He evitado este error asignando un espacio de trabajo único y scratchWorkspace para cada proceso utilizando una carpeta temporal tempfile.mkdtemp.

jonah
fuente
Ya uso espacios de trabajo únicos, pero comprobaré que scratchWorkspace también sea único. Supongo que no, ya que está escribiendo en el directorio% TEMP%.
blord-castillo
Jonás tiene razón. Estoy procesando miles de rásteres en un solo directorio en 5 hilos simultáneos; Establecer un espacio de trabajo scratch único para cada uno es la única solución que me ha funcionado. La salida a carpetas únicas, como algunos han recomendado, solo crea más trabajo para más tarde ... eventualmente los quiero a todos en el mismo directorio.
Tom
¡Qué dolor en la parte trasera! ¡Usar el espacio de trabajo único de scratch con el multiprocesamiento funcionó, pero Dios mío, administrar las carpetas adicionales y luego tratar de eliminarlas con bloqueos arcpy es ridículo!
D_C
3

He encontrado esto también y aún no he encontrado una solución de sonido. Mi trabajo es 1) para asegurarme de que la tarea de multiprocesamiento sea lo suficientemente sólida como para verificar si las tareas están completas o no, y luego crear una nueva lista de trabajos. 2) programe dos scripts para que se inicien cada 10-15 minutos. Una secuencia de comandos contiene un comando para eliminar procesos de Python en ejecución seleccionados y la segunda relanza la secuencia de comandos de multiprocesamiento deseada. Básicamente, esto actualiza el grupo de multiprocesamiento. La secuencia de comandos kill es algo como esto:

def read_pid():
    inFile = open("E:/temp/pid.csv")
    for line in inFile:
        pid = str(line)
    inFile.close()
    return pid

def kill():
    if os.path.exists("E:/temp/pid.csv")==True:
        pid = read_pid()
        PROCESS_TERMINATE=1
        handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE,False,pid)
        ctypes.windll.kernel32.TerminateProcess(handle,-1)
        ctypes.windll.kernel32.CloseHandle(handle)
    else:
        return

Cada vez que lanzo el script deseado, hago que escriba su PID en un csv.

metasequoia
fuente
2

Descubrí que recibía el error INFADI al intentar que varios hilos / núcleos guardaran y modificaran rásteres en una carpeta. Asignar una subcarpeta a cada tarea para resultados parece resolver el problema. Creo que el problema tenía que ver con múltiples lecturas / escrituras en archivos periféricos asociados con el ráster (por ejemplo, la carpeta "info"). Ahora también empleo las siguientes precauciones:

import arcpy,multiprocessing,random

def run(foo,c):
    tempFolder = os.path.join("Z:/temp/",'temp_%s'%(str(c)))
    if not os.path.exists(tempFolder): os.mkdir(tempFolder)
    arcpy.env.scratchWorkspace = tempFolder
    arcpy.env.Workspace = tempFolder

    # create unique object in memory, run task, then delete unique object in memory
    tempMem = str(rnd)
    try:arcpy.Delete_management(tempMem)
    except:pass

    <tasks> #output to appropriate subfolder

    arcpy.Delete_management(tempMem)

if __name__ == '__main__':
    cores = 3
    pool = multiprocessing.Pool(cores)
    count = 0
    for foo in bar:
        pool.apply_async(run,(foo,c))
        count +=1
    pool.close()
    pool.join()
metasequoia
fuente
Parece que nunca recibo errores al escribir múltiples GRID en la misma carpeta a través de múltiples hilos. El único problema parece ser que hacerlo ralentiza el procesamiento y prácticamente invalida el enhebrado, ya que solo escribe un ráster a la vez.
Tom