我有一段fortran代码从STDIN读取一些数字并将结果写入STDOUT . 例如:
do
read (*,*) x
y = x*x
write (*,*) y
enddo
所以我可以从shell启动程序并获得以下输入序列/ outputs :
5
25.0
2.5
6.25
现在我需要在python中执行此操作 . 在与subprocess.Popen徒手摔跤并查看本网站上的旧问题之后,我决定使用pexpect.spawn:
import pexpect, os
p = pexpect.spawn('squarer')
p.setecho(False)
p.write("2.5" + os.linesep)
res = p.readline()
它的工作原理 . 问题是,我需要在python和我的fortran程序之间传递 real 数据是一个100,000(或更多)双精度浮点数组 . 如果它们包含在名为 x
的数组中,那么
p.write(' '.join(["%.10f"%k for k in x]) + os.linesep)
从pexpect发出以下错误消息超时:
buffer (last 100 chars):
before (last 100 chars):
after: <class 'pexpect.TIMEOUT'>
match: None
match_index: None
exitstatus: None
flag_eof: False
pid: 8574
child_fd: 3
closed: False
timeout: 30
delimiter: <class 'pexpect.EOF'>
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1
除非 x
少于303个元素 . 有没有办法将大量数据传入/传出另一个程序的STDIN / STDOUT?
我试过将数据分成更小的块,但后来我失去了 lot 的速度 .
提前致谢 .
5 回答
使用子进程模块找到了一个解决方案,所以我在这里发布它以供参考,如果有人需要做同样的事情 .
使用名为“optimizer”的外部程序调用该类,如下所示:
在fortran方面(程序编译为给出可执行文件'optimizer'),将读入一个500元素的向量:
并将被写出来:
就是这样!我用状态向量测试了多达200,000个元素(这是我现在需要的上限) . 希望这能帮助除我以外的其他人 . 这个解决方案适用于ifort和xlf90,但由于某种原因我不理解gfortran .
示例squarer.py程序(它恰好在Python中,使用您的Fortran可执行文件):
示例target.py程序:
main
函数包含您将使用的代码:设置Companion
对象,companion.send
一长行数据,companion.recv
一行 . 根据需要重复 .我认为你只在这里添加一个换行符:
而不是每行添加一个 .
看起来你超时(默认超时,我相信,30秒),因为准备,发送,接收和处理大量数据需要花费大量时间 . 对于the docs,
timeout=
是expect
方法的可选命名参数,您可以在初始化程序中设置默认超时,这可以通过对源进行粗略查找(或者,最坏的情况,通过黑客攻击来创建) ) .如果Fortran程序一次读取并保存(比方说)100个项目,并且有提示,则同步将变得非常容易 . 您可以为此目的修改Fortran代码,还是宁愿选择无证/黑客方法?
这是一个巨大的简化:将Python分解为两件事 .
squarer
应用程序是您的Fortran代码 . 从stdin读取,写入stdout .你的
source.py
就是你的Python或者,也许更简单一些,即
你的
sink.py
是这样的 .分离源,平方和接收器可以获得3个独立的进程(而不是2个),并将使用更多内核 . 更多核心==更多并发==更有趣 .