You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python多次调用Fortran可执行文件且无需重复创建shell进程

问题描述

我需要从Python中运行一个已编译的Fortran数值模型,使用F2PY编译该程序需要对Fortran例程做大量修改,实现复杂度过高,因此选择通过subprocess模块直接调用其可执行文件。
当前需要将该程序调用数千次,发现每次调用都生成新shell的实现方式大幅拖慢了整体运行效率。我当前的实现代码如下(暂无法提供可复现示例):

import os
import subprocess

foo_path = '/path/to/compiled/program/'
program_dir = os.path.join(foo_path, "FOO")            # FOO是Fortran可执行文件
instruction = program_dir + " < nlst"                  # 需要给FOO传入一个名为nlst的文本配置文件

subprocess.call(instruction, shell=True, cwd=foo_path) # 运行可执行文件

这种放在循环中运行的方式功能正常,FOO会生成文本输出文件供Python读取,但我希望可以保持shell处于激活状态,每次仅向其传入nlst配置文件的路径即可运行程序;另一种可选方案是启动一个空闲shell进程,等待接收类似./FOO < nlst的指令字符串再执行,但我不确定具体要如何实现,请问有没有可行的方案?
[补充]我尝试过如下写法,但communicate方法调用后会终止process进程,无法执行第二次调用:

from subprocess import Popen, PIPE

foo_path = '/path/to/FOO/'
process = Popen(['bash'], stdin=PIPE, cwd=foo_path)
process.communicate(b'./FOO < nlst')
可行方案

communicate方法的设计逻辑就是等待子进程终止后再返回,同时会自动关闭标准输入流,因此确实无法支持多次调用的需求,你可以直接向常驻shell进程的stdin管道逐行写入执行命令,核心实现逻辑如下:

  • 启动常驻bash进程时,同时打开stdout和stderr管道,方便后续判断命令执行状态
  • 每写入一条完整命令后添加换行符\n,让shell识别到指令结束
  • 写入后手动调用flush方法清空缓冲区,确保命令立刻被shell接收执行
    示例代码如下:
from subprocess import Popen, PIPE
import time

foo_path = '/path/to/FOO/'
# 启动常驻bash进程,设置文本模式更方便操作字符串,不需要手动转字节
process = Popen(['bash'], stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True, cwd=foo_path)

# 你要循环执行的nlst文件列表
nlst_list = ["nlst1", "nlst2", "nlst3"] # 替换为你实际的配置文件列表

for nlst_file in nlst_list:
    # 写入执行命令,末尾加换行
    process.stdin.write(f"./FOO < {nlst_file}\n")
    # 加一个标记命令,用于判断当前FOO执行完成,避免异步时序问题
    process.stdin.write("echo 'CMD_FINISHED'\n")
    process.stdin.flush()
    
    # 读取输出直到遇到我们定义的结束标记,确认命令执行完成
    while True:
        output_line = process.stdout.readline()
        if output_line.strip() == 'CMD_FINISHED':
            break
        # 如果你需要捕获FOO的输出可以在这里处理
        # print(output_line)
    
    # 这里可以加读取FOO生成的输出文件的逻辑
    print(f"{nlst_file} 执行完成")

# 所有任务执行完后,给shell发退出命令,正常关闭进程
process.stdin.write("exit\n")
process.stdin.flush()
process.wait()

额外优化建议

  • 如果你每次只是修改nlst里的少量参数,可以直接把配置内容通过stdin传给FOO,不需要每次生成新的nlst文件,能进一步减少磁盘IO开销,速度更快
  • 如果FOO本身没有后台运行逻辑,不需要额外加超时判断,上述标记法已经可以稳定判断执行结束

内容的提问来源于stack exchange,提问作者Lacococha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 17:27:03