2015-07-19 40 views
-2

在python中,可以使用(例如)subprocess.Popen运行程序并根据需要重定向stdout或stderr,以便处理输出。从Python中调用写入文件的程序 - 我可以避免IO吗?

你可以用被调用的程序直接写入文件吗?

我有一个fortran程序,它将结果写入文件(它也将中间结果写为文件)。现在,我从Python(2.7)调用这个程序,等待它完成,然后读取输出文件。

但是我必须经常这样做,并行,并且I/O占用运行时间的很大一部分。

不修改fortran程序,直接写入文件(不是标准输出),我可以以某种方式直接从python捕获I/O,避开写入磁盘?

回答

1

在不修改Fortran程序的情况下执行此操作的最简单方法可能是named pipes - 与管道相同的想法,但是是持久性的(不受任何一个进程的束缚)并且通过文件系统可见。

比方说,我们有一个简单的Fortran程序:

program writer 

    integer,parameter :: u=10 
    integer :: i 
    real :: x 
    open(u,file='output.dat') 
    do i=1,10 
     x = (i-1)*0.5 
     write(u,*) i, x, x**2, x**3 
    end do 
    close(u) 
end program writer 

其中,在运行时,提供所需的输出:

 1 0.000000  0.000000  0.000000 
     2 0.5000000  0.2500000  0.1250000 
     3 1.000000  1.000000  1.000000 
     4 1.500000  2.250000  3.375000 
     5 2.000000  4.000000  8.000000 
     6 2.500000  6.250000  15.62500 
     7 3.000000  9.000000  27.00000 
     8 3.500000  12.25000  42.87500 
     9 4.000000  16.00000  64.00000 
     10 4.500000  20.25000  91.12500 

我们知道输出文件将是output.dat(因为它是硬编码或作为选项提供)。

我们可以创建一个名为output.dat的命名管道,并从另一个程序中读取它,它的行为就好像我们将现有Fortran程序的输出传送到另一个命令 - 即使Fortran程序不是写到标准输出或标准错误:

$ rm output.dat 
$ mkfifo output.dat 
$ awk '{print "Got line: ",$0}' < output.dat & 
[1] 69609 
$ ./writer 
$ Got line:    1 0.000000  0.000000  0.000000 
Got line:    2 0.5000000  0.2500000  0.1250000 
Got line:    3 1.000000  1.000000  1.000000 
Got line:    4 1.500000  2.250000  3.375000 
Got line:    5 2.000000  4.000000  8.000000 
Got line:    6 2.500000  6.250000  15.62500 
Got line:    7 3.000000  9.000000  27.00000 
Got line:    8 3.500000  12.25000  42.87500 
Got line:    9 4.000000  16.00000  64.00000 
Got line:   10 4.500000  20.25000  91.12500 

[1]+ Done     awk '{print "Got line: ",$0}' < output.dat 
$ rm output.dat 

真棒 - 我们刚刚写程序写入(只要它知道)的文件,我们不得不awk从该文件中,一行一行地读,因为它出现了。

所以现在我们可以做到这一点,并推出从阅读中的Python:

import os 
import subprocess 

if __name__ == "__main__": 

    outfilename = "output.dat" 
    os.mkfifo(outfilename,0777) 

    i = [] 
    x = [] 
    xsquared = [] 

    writer = subprocess.Popen("./writer") 

    with open(outfilename,'r') as fortranoutput: 
     for line in fortranoutput: 
      items=line.split() 
      i.append(int(items[0])) 
      x.append(float(items[1])) 
      xsquared.append(float(items[2])) 

    print "Got: i = ", i 
    print "  x = ", x 
    print "  x^2= ", xsquared 

和运行提供了:

$ python readFifo.py 
Got: i = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
    x = [0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5] 
    x^2= [0.0, 0.25, 1.0, 2.25, 4.0, 6.25, 9.0, 12.25, 16.0, 20.25] 
+0

非常感谢您详细的解答。这正是我需要的。 – user2660966

相关问题