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

Python中Popen与communicate调用Molly软件报错求助

解决Molly光谱软件子进程调用的Fortran EOF错误

这个Fortran runtime error本质是Molly在尝试从标准输入读取命令时,输入流提前被关闭了——简单说就是你的Python脚本没有正确把命令传递给Molly,或者传递过程中stdin意外中断了。我来拆解下你的两种写法的问题,再给你可行的解决方案:

为什么你的写法会出错?

写法一的问题

subprocess.Popen.communicate()这个方法是一次性的:它会把你传入的输入发送给子进程,然后等待进程结束,同时自动关闭stdin/stdout/stderr。你第一次调用communicate()发送load命令后,Molly的stdin已经被关闭了,第二次调用时根本没有输入可以传递,Molly自然就读到了EOF,触发报错。

写法二的问题

虽然用了with块管理进程,但你用print()写stdin时,Python默认会缓冲输出——也就是说命令可能还停留在Python的缓冲区里,没真正发送给Molly;另外你没有明确等待Molly处理完所有命令,也没有告诉Molly“输入结束了”,导致它要么没收到完整命令,要么一直等待输入直到意外读到EOF。

正确的解决方案

方案1:一次性发送所有命令(推荐)

既然终端里是按回车执行每个命令,那我们把所有命令用换行符\n拼接起来,用一次communicate()发送,完美模拟终端的输入流程:

from subprocess import Popen, PIPE, DEVNULL

# 把两个命令用换行符拼接,最后加一个换行模拟终端回车操作
commands = 'load average_y_template1.mol 1 1000 1\n@macro_molly.txt\n'
# 启动Molly进程,捕获错误输出方便排查问题
process = Popen(
    "/home/ayozeah/trm-software/molly/molly",
    stdin=PIPE,
    stdout=DEVNULL,  # 如果需要查看Molly的输出,可以改成PIPE
    stderr=PIPE,
    shell=False
)
# 发送命令并等待进程结束
stdout, stderr = process.communicate(input=commands.encode())

# 检查运行结果
if process.returncode != 0:
    print(f"Molly运行失败,错误信息:\n{stderr.decode()}")
else:
    print("Molly命令执行成功!")

方案2:分步发送命令(适合需要交互的场景)

如果你确实需要分步发送命令(比如根据前一个命令的输出决定下一个命令),要确保每次发送后强制刷新缓冲区,最后关闭stdin并等待进程完成:

from subprocess import Popen, PIPE, DEVNULL

with Popen(
    "/home/ayozeah/trm-software/molly/molly",
    stdin=PIPE,
    stdout=DEVNULL,
    stderr=PIPE,
    bufsize=0,  # 禁用缓冲,确保命令立即发送给Molly
    text=True   # 直接处理字符串,无需手动编码
) as process:
    # 发送第一个命令并手动换行
    process.stdin.write('load average_y_template1.mol 1 1000 1\n')
    process.stdin.flush()  # 强制把缓冲区内容发送给Molly
    
    # 发送第二个命令
    process.stdin.write('@macro_molly.txt\n')
    process.stdin.flush()
    
    # 关闭stdin,明确告诉Molly所有输入已发送
    process.stdin.close()
    
    # 等待进程完成并获取错误信息
    stderr = process.communicate()[1]
    if process.returncode != 0:
        print(f"Molly运行失败,错误信息:\n{stderr}")
    else:
        print("Molly命令执行成功!")

关键注意点

  • communicate()只能调用一次,它会帮你处理所有流的关闭和进程等待,是子进程交互最安全的方式。
  • 如果手动写stdin,一定要用flush()或者设置bufsize=0避免缓冲问题——这是很多子进程交互出错的核心原因。
  • 终端里你最后会按Ctrl+D发送EOF,对应脚本里就是关闭stdin或者调用communicate(),让Molly知道没有更多输入了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:27:26