python.multiprocessing i „FATAL ERROR (INFADI) MISSING DIRECTORY”

9

Podczas próby wykonywania wielu procesów za pomocą Arcpy, od czasu do czasu pojawia się ten błąd:

FATAL ERROR (INFADI)
MISSING DIRECTORY

Nie mam pojęcia, co powoduje ten błąd i powoduje awarię procesu Pythona, uniemożliwiając uzyskanie na nim śledzenia. Występuje podczas pisania końcowego wyniku rastra z długiego modelu dźwięku.

Czasami towarzyszy temu błąd

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

Gdzie% Temp jest parsowane, a #### to losowa 4-cyfrowa liczba. Jest to niezwykłe, ponieważ każdy proces ma własny obszar roboczy, w którym należy zapisać większość plików.

Problemem nie są dane wejściowe ... Mogę ponownie uruchomić program na błędnych danych wejściowych i będzie działał poprawnie.

blord-castillo
źródło
Wrócę do tego wkrótce, ale muszę teraz pracować nad innym modelem.
blord-castillo

Odpowiedzi:

6

Oto kilka rzeczy do sprawdzenia:

Czy używasz kursorów? Wypuszczasz je? Czy próbujesz ponownie użyć obiektów w różnych procesach? Czy udostępniasz tę samą lokalizację tymczasową? Czy zajmujesz się przetwarzaniem pamięci?

Ogólnie rzecz biorąc, arcpy jest tylko owijaniem wokół obiektów com, a każdy rodzaj wieloprocesowości będzie trudny.

Jamie
źródło
4

Odkryłem, że ten problem pojawia się, gdy arcpy.env.workspace i arcpy.env.scratchWorkspace są takie same dla dwóch różnych procesów. Arc zapisuje prawie wszystkie pośrednie rastry w obszarze roboczym (lub obszarze roboczym rysowania) w formacie ESRI GRID. Nie można jednocześnie zapisywać dwóch rastrów ESRI GRID w tym samym katalogu ze względu na strukturę pseudo-bazy danych formatu (folder informacyjny zawiera unikatowe klucze dla każdego rastra).

Uniknąłem tego błędu, przypisując unikalny obszar roboczy i scratchWorkspace dla każdego procesu za pomocą tymczasowego folderu tempfile.mkdtemp.

Jonasz
źródło
Korzystam już z unikalnych obszarów roboczych, ale jeszcze raz sprawdzę, czy scratchWorkspace jest również wyjątkowy. Chyba nie, ponieważ pisze do katalogu% TEMP%.
blord-castillo
Jonasz ma rację. Przetwarzam tysiące rastrów w jednym katalogu w 5 równoczesnych wątkach; ustawienie unikatowego obszaru roboczego dla każdego jest jedynym rozwiązaniem, które działało dla mnie. Przesyłanie do unikatowych folderów, jak niektórzy zalecają, po prostu tworzy więcej pracy na później ... ostatecznie chcę je wszystkie w tym samym katalogu.
Tom
Co za ból z tyłu! Używanie unikalnego obszaru roboczego scratch przy wieloprocesowym działaniu działało, ale mój Boże, zarządzanie dodatkowymi folderami, a następnie próba ich usunięcia za pomocą arkadowych blokad jest absurdalna !!
D_C
3

Zetknąłem się z tym i nie znalazłem jeszcze rozwiązania dźwiękowego. Moje obejście to 1), aby upewnić się, że zadanie wieloprocesowe jest wystarczająco solidne, aby sprawdzić, czy zadania są ukończone, czy nie, a następnie utworzyć nową listę zadań. 2) zaplanuj uruchamianie dwóch skryptów co 10-15 minut. Jeden skrypt zawiera polecenie zabicia wybranych uruchomionych procesów Pythona, a drugi ponownie uruchamia żądany skrypt wieloprocesowy. Zasadniczo odświeża pulę wieloprocesową. Skrypt zabicia jest mniej więcej taki:

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

Przy każdym uruchomieniu pożądanego skryptu zapisuję jego identyfikator PID do pliku csv.

metasequoia
źródło
2

Odkryłem, że dostaję błąd INFADI, gdy próbuję zapisać wiele wątków / rdzeni i zmodyfikować rastry w jednym folderze. Przypisanie podfolderu do każdego zadania dla wyników wydaje się rozwiązać problem. Uważam, że problem dotyczy wielu odczytów / zapisów w plikach peryferyjnych powiązanych z rastrem (np. Folder „info”). Teraz stosuję również następujące środki ostrożności:

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
źródło
Wydaje się, że nigdy nie pojawiają się błędy związane z pisaniem wielu GRID-ów w tym samym folderze przez wiele wątków. Jedynym problemem wydaje się być to, że spowalnia to przetwarzanie i praktycznie unieważnia wątkowanie, ponieważ zapisuje tylko jeden raster na raz.
Tom