4

Python から FORTRAN exe を実行しています。FORTRAN exe が完了するまでに数分かかります。したがって、exe の終了時にコールバックを起動する必要があります。exe は Python に何も返しませんが、コールバック関数では、Python を使用して FORTRAN からの出力テキスト ファイルを解析します。

このために私は と を使用concurrent.futuresadd_done_callback()ていますが、うまくいきます。しかし、Web サービスのこの部分とsubprocess.call() / Popen()、FORTRAN exe が実行されたときに戻るように呼び出す Python メソッドが必要です。次に、FORTRAN が完了すると、コールバック関数が呼び出されます。

def fortran_callback(run_type, jid):

    return "Fortran finished executing"

def fortran_execute():

    from concurrent.futures import ThreadPoolExecutor as Pool

    args = "fortran.exe arg1 arg2"

    pool = Pool(max_workers=1)
    future = pool.submit(subprocess.call, args, shell=1)
    future.add_done_callback(fortran_callback(run_type, jid))
    pool.shutdown(wait=False)

    return "Fortran executed"

フォームが送信されたときに fortran_execute() が呼び出され、FORTRAN が完了するのを待たずに「Fortran が実行されました」を返したい。

現在、Python メソッドは FORTRAN の完了を待たずに戻りますが、戻り時にコールバックもトリガーします。FORTRAN プロセスは引き続き実行され、最終的に完了するとコールバック関数を呼び出そうとしますが、futureが存在しないため例外がスローされTypeError: 'NoneType' object is not callableます。

subprocessでexeを開始し、関数を返し、exeの実行が終了したときにのみコールバックメソッドを呼び出すために、ここで何が欠けていますか?

4

1 に答える 1

7

わかりました。これで、あなたが何を望んでいて、何が問題なのかがわかりました。

def fortran_callback(future):
    print(future.run_type, future.jid)
    return "Fortran finished executing"

def fortran_execute():

    from concurrent.futures import ProcessPoolExecutor as Pool

    args = "sleep 2; echo complete"

    pool = Pool(max_workers=1)
    future = pool.submit(subprocess.call, args, shell=1)
    future.run_type = "run_type"
    future.jid = "jid"
    future.add_done_callback(fortran_callback)

    print("Fortran executed")


if __name__ == '__main__':
    import subprocess
    fortran_execute()

上記のコードを実行すると、次の出力が得られます。

$ python3 test.py                                                                                                                                                      
Fortran executed
complete
run_type jid
  1. fortran_callbackThreadPool を使用しても問題ありませんが、計算コストが高い場合は ProcessPool の方が適しています
  2. Callback は、future オブジェクトであるパラメーターを 1 つだけ受け取るため、必要なことは、futureの属性を介してパラメーターを渡すことです。
于 2015-03-06T11:59:21.133 に答える