2015-07-19 41 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

相關問題