4

我正在从 Python 执行 FORTRAN exe。FORTRAN exe 需要几分钟才能完成;因此,我需要在 exe 完成时触发回调。exe 不会将任何内容返回给 Python,但在回调函数中,我将使用 Python 解析来自 FORTRAN 的输出文本文件。

为此,我正在使用concurrent.futuresand add_done_callback(),它可以工作。但是 Web 服务的这一部分,我需要在执行 FORTRAN exe 后调用subprocess.call() / Popen()返回的 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

我在这里缺少什么来启动 exe subprocess,让函数返回,然后只有在 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. 使用 ThreadPool 是可以的,但 ProcessPool 如果fortran_callback计算量大则更好
  2. 回调只接受一个参数,即未来对象,因此您需要做的是通过future的属性传递参数。
于 2015-03-06T11:59:21.133 回答