python.multiprocessing et "FATAL ERROR (INFADI) MISSING DIRECTORY"

9

En essayant de faire du multitraitement avec arcpy, je rencontre parfois cette erreur:

FATAL ERROR (INFADI)
MISSING DIRECTORY

Je n'ai aucune idée de ce qui déclenche cette erreur, et il bloque le processus python, ce qui rend impossible d'obtenir un suivi. Il se produit lors de l'écriture de la sortie matricielle finale d'un long modèle sonore.

Elle est parfois accompagnée d'une erreur

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

Où% Temp est analysé correctement et #### est un nombre aléatoire à 4 chiffres. Cela est inhabituel car chaque processus a son propre espace de travail, où la plupart des fichiers doivent être écrits.

Le problème n'est pas les données d'entrée ... Je peux relancer le programme sur les entrées qui ont échoué et il fonctionnera correctement.

blord-castillo
la source
Je reviendrai bientôt sur celui-ci, mais je dois travailler sur un modèle différent en ce moment.
blord-castillo

Réponses:

6

Voici quelques éléments à vérifier:

Utilisez-vous des curseurs? Les relâchez-vous? Essayez-vous de réutiliser des objets dans différents processus? Partagez-vous le même emplacement temporaire? Faites-vous dans le traitement de la mémoire?

En général, l'arcpy n'est qu'un wrapper autour des objets com et tout type de multitraitement sera délicat.

Jamie
la source
4

J'ai trouvé que ce problème se produit lorsque arcpy.env.workspace et arcpy.env.scratchWorkspace sont identiques pour deux processus différents. Arc écrit presque tous les rasters intermédiaires dans l'espace de travail (ou espace de travail de travail) au format ESRI GRID. Vous ne pouvez pas écrire deux rasters ESRI GRID dans le même répertoire en même temps en raison de la structure de la pseudo-base de données du format (le dossier info contient des clés uniques pour chaque raster).

J'ai évité cette erreur en attribuant un espace de travail unique et scratchWorkspace pour chaque processus à l'aide d'un dossier temporaire tempfile.mkdtemp.

Jonah
la source
J'utilise déjà des espaces de travail uniques, mais je vérifierai également que scratchWorkspace est également unique. Je suppose que non car il écrit dans le répertoire% TEMP%.
blord-castillo
Jonah a raison. Je traite des milliers de rasters dans un seul répertoire sur 5 threads simultanés; définir un espace de travail scratch unique pour chacun est la seule solution qui a fonctionné pour moi. La sortie vers des dossiers uniques, comme certains l'ont recommandé, crée simplement plus de travail pour plus tard ... finalement, je les veux tous dans le même répertoire.
Tom
Quelle douleur à l'arrière! Utiliser l'espace de travail scratch unique avec le multitraitement a fonctionné, mais mon dieu, gérer les dossiers supplémentaires puis essayer de les supprimer avec des verrous arcpy est ridicule !!
D_C
3

J'ai également rencontré cela et je n'ai pas encore trouvé de solution sonore. Mon travail consiste à 1) m'assurer que la tâche de multitraitement est suffisamment robuste pour vérifier si les tâches sont terminées ou non, puis créer une nouvelle liste de tâches. 2) planifiez le lancement de deux scripts toutes les 10 à 15 minutes. Un script contient une commande pour tuer certains processus python en cours d'exécution et le second relance le script de multitraitement souhaité. Essentiellement, cela actualise le pool de multitraitement. Le script kill est quelque chose comme ceci:

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

Chaque lancement du script souhaité, je l'ai écrire son PID sur un csv.

metasequoia
la source
2

J'ai constaté que j'obtenais l'erreur INFADI lorsque j'essayais d'enregistrer et de modifier des rasters dans un seul dossier. L'affectation d'un sous-dossier à chaque tâche pour les sorties semble résoudre le problème. Je crois que le problème était dû à plusieurs lectures / écritures sur des fichiers périphériques associés au raster (par exemple le dossier "info"). J'emploie désormais également les précautions suivantes:

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
la source
Je ne semble jamais obtenir d'erreurs en écrivant plusieurs GRID dans le même dossier via plusieurs threads. Le seul problème semble être que cela ralentit le traitement et invalide virtuellement le threading, car il n'écrit qu'un raster à la fois.
Tom