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

9

Beim Versuch, Multiprocessing mit arcpy durchzuführen, tritt gelegentlich der folgende Fehler auf:

FATAL ERROR (INFADI)
MISSING DIRECTORY

Ich habe keine Ahnung, was diesen Fehler auslöst, und er stürzt den Python-Prozess ab, sodass es unmöglich ist, einen Traceback darauf zu erhalten. Dies tritt beim Schreiben der endgültigen Rasterausgabe eines langen Soundmodells auf.

Es wird manchmal von einem Fehler begleitet

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

Wobei% Temp korrekt analysiert wird und #### eine zufällige 4-stellige Zahl ist. Dies ist ungewöhnlich, da jeder Prozess einen eigenen Arbeitsbereich hat, in den die meisten Dateien geschrieben werden sollten.

Das Problem sind nicht die Eingabedaten ... Ich kann das Programm auf den fehlgeschlagenen Eingaben erneut ausführen und es wird korrekt ausgeführt.

Blord-Castillo
quelle
Ich werde bald darauf zurückkommen, muss aber jetzt an einem anderen Modell arbeiten.
Blord-Castillo

Antworten:

6

Hier sind einige Dinge zu überprüfen:

Verwenden Sie Cursor? Veröffentlichen Sie sie? Versuchen Sie, Objekte in verschiedenen Prozessen wiederzuverwenden? Teilen Sie den gleichen temporären Standort? Machst du in der Speicherverarbeitung?

Im Allgemeinen ist der Arcpy nur ein Wrapper um die COM-Objekte, und jede Art der Mehrfachverarbeitung ist schwierig.

Jamie
quelle
4

Ich habe festgestellt, dass dieses Problem auftritt, wenn arcpy.env.workspace und arcpy.env.scratchWorkspace für zwei verschiedene Prozesse identisch sind. Arc schreibt fast alle Zwischenraster im ESRI GRID-Format in den Arbeitsbereich (oder Scratch-Arbeitsbereich). Aufgrund der Pseudodatenbankstruktur des Formats können Sie nicht zwei ESRI GRID-Raster gleichzeitig in dasselbe Verzeichnis schreiben (der Info-Ordner enthält eindeutige Schlüssel für jedes Raster).

Ich habe diesen Fehler vermieden, indem ich jedem Prozess mithilfe eines temporären Ordners tempfile.mkdtemp einen eindeutigen Arbeitsbereich und einen Arbeitsbereich zugewiesen habe.

Jona
quelle
Ich verwende bereits eindeutige Arbeitsbereiche, werde jedoch überprüfen, ob ScratchWorkspace auch eindeutig ist. Ich vermute nicht, da es in das Verzeichnis% TEMP% schreibt.
Blord-Castillo
Jonah ist richtig. Ich verarbeite Tausende von Rastern in einem einzigen Verzeichnis über 5 Threads gleichzeitig. Das Einstellen eines eindeutigen Arbeitsbereichs für jeden ist die einzige Lösung, die für mich funktioniert hat. Das Ausgeben in eindeutige Ordner, wie einige empfohlen haben, schafft nur mehr Arbeit für später ... schließlich möchte ich, dass sie sich alle im selben Verzeichnis befinden.
Tom
Was für ein Schmerz auf der Rückseite! Die Verwendung des einzigartigen Scratch-Arbeitsbereichs mit der Mehrfachverarbeitung hat funktioniert, aber mein Gott, es ist lächerlich, die zusätzlichen Ordner zu verwalten und dann zu versuchen, sie mit bogenförmigen Sperren zu löschen !!
D_C
3

Ich bin auch darauf gestoßen und habe noch keinen Soundfix gefunden. Meine Problemumgehung besteht darin, 1) sicherzustellen, dass die Mehrfachverarbeitungsaufgabe robust genug ist, um zu überprüfen, ob die Aufgaben abgeschlossen sind oder nicht, und dann eine neue Jobliste zu erstellen. 2) Planen Sie zwei Skripte, die alle 10-15 Minuten gestartet werden sollen. Ein Skript enthält einen Befehl zum Beenden ausgewählter laufender Python-Prozesse und das zweite startet das gewünschte Multiprozessorskript neu. Dies aktualisiert im Wesentlichen den Multiprozessor-Pool. Das Kill-Skript sieht ungefähr so ​​aus:

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

Bei jedem Start des gewünschten Skripts muss die PID in eine CSV geschrieben werden.

Metasequoia
quelle
2

Ich habe festgestellt, dass beim Versuch, mehrere Threads / Kerne in einem Ordner zu speichern und zu ändern, der INFADI-Fehler aufgetreten ist. Das Zuweisen eines Unterordners zu jeder Aufgabe für Ausgaben scheint das Problem zu lösen. Ich glaube, dass das Problem mit mehreren Lese- / Schreibvorgängen in Peripheriedateien zu tun hat, die dem Raster zugeordnet sind (z. B. dem Ordner "info"). Ich wende jetzt auch die folgenden Vorsichtsmaßnahmen an:

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
quelle
Ich scheine nie Fehler zu bekommen, wenn ich mehrere GRIDs über mehrere Threads in denselben Ordner schreibe. Das einzige Problem scheint zu sein, dass dies die Verarbeitung verlangsamt und das Threading praktisch ungültig macht, da jeweils nur ein Raster geschrieben wird.
Tom