python.multiprocessingと「致命的なエラー(INFADI)MISSING DIRECTORY」


9

arcpyでマルチプロセッシングを実行しようとしているときに、時々このエラーに遭遇します:

FATAL ERROR (INFADI)
MISSING DIRECTORY

私はこのエラーを引き起こしている原因を知りません、そしてそれはpythonプロセスをクラッシュさせ、トレースバックを取得することを不可能にします。これは、長いサウンドモデルから最終的なラスター出力を書き込むときに発生します。

エラーが発生する場合があります

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

ここで、%Tempは解析された相関性で、####はランダムな4桁の数字です。各プロセスには独自のワークスペースがあり、ほとんどのファイルを書き込む必要があるため、これは異常です。

問題は入力データではありません...失敗した入力でプログラムを再実行すると、正しく実行されます。


私はすぐにこれに戻りますが、今は別のモデルに取り組む必要があります。
blord-castillo

回答:


6

チェックするべきいくつかの事柄はここにあります:

カーソルを使用していますか?それらを解放していますか?別のプロセスでオブジェクトを再利用しようとしていますか?同じ一時的な場所を共有していますか?メモリ処理を行っていますか?

一般に、arcpyはcomオブジェクトのラッパーにすぎず、あらゆるタイプのマルチプロセッシングは扱いにくいものになります。


4

この問題は、arcpy.env.workspaceとarcpy.env.scratchWorkspaceが2つの異なるプロセスで同じ場合に発生することがわかりました。Arcは、ほぼすべての中間ラスタをESRI GRID形式でワークスペース(またはスクラッチワークスペース)に書き込みます。形式の疑似データベース構造により、2つのESRI GRIDラスタを同じディレクトリに同時に書き込むことはできません(情報フォルダには各ラスタの一意のキーが保持されます)。

一時tempfile.mkdtempフォルダーを使用して各プロセスに一意のワークスペースとscratchWorkspaceを割り当てることで、このエラーを回避しました。


私はすでに一意のワークスペースを使用していますが、scratchWorkspaceも一意であることを再確認します。%TEMP%ディレクトリに書き込んでいるので、私はそうは思いません。
blord-castillo 2013

ヨナは正解です。5つの同時スレッドで単一のディレクトリで数千のラスタを処理しています。それぞれに独自のスクラッチワークスペースを設定することが、私にとって有効な唯一のソリューションです。いくつかの人が推奨しているように、一意のフォルダーに出力すると、あとで作業できるようになります。
トム

裏側のなんて痛い!マルチプロセッシングでユニークなスクラッチワークスペースを使用することは機能しましたが、私の神は、余分なフォルダーを管理してから、arcpyロックでそれらを削除しようとするのはばかげています!!
D_C

3

私もこれに遭遇し、まだサウンドの修正を見つけることができていません。私の回避策は、1)マルチプロセッシングタスクが、タスクが完了しているかどうかをチェックして新しいジョブリストを作成するのに十分なほど堅牢であることを確認することです。2)2つのスクリプトを10〜15分ごとに起動するようにスケジュールします。1つのスクリプトには、選択した実行中のpythonプロセスを強制終了するコマンドが含まれ、2番目のスクリプトには、目的のマルチプロセッシングスクリプトが再起動されます。基本的に、これによりマルチプロセッシングプールが更新されます。killスクリプトは次のようなものです。

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

目的のスクリプトを起動するたびに、そのPIDをcsvに書き込みます。



2

複数のスレッド/コアで1つのフォルダーのラスターを保存および変更しようとすると、INFADIエラーが発生することがわかりました。出力用に各タスクにサブフォルダーを割り当てると、問題が解決するようです。この問題は、ラスターに関連付けられた周辺ファイル(「info」フォ​​ルダーなど)に対する複数の読み取り/書き込みに関係していると思います。私は現在、次の予防策も採用しています。

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()

複数のスレッドを介して同じフォルダーに複数のGRIDを書き込むと、エラーが発生するようには見えません。唯一の問題は、一度に1つのラスタしか書き込まないため、処理が遅くなり、スレッドが実質的に無効になることです。
トム
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.