2013-03-28 34 views
3

我試圖從Python的shell中執行Fortran程序。 我使用subprocess來調用Fortran程序並傳遞參數(需要兩個輸入文件)。這就是我要做的事:Python子程序沒有正確執行程序

? FORTRAN Runtime Error: 
? Attempt to read past end of file 
? READ(UNIT=22,... 

這是不是問題與輸入文件或Fortran程序:

COMMAND = '/path/to/FORTRAN/program << !\n' + INPUT_FILE1 + '\n' + INPUT_FILE2 +'\n!' 
return = subprocess.call(COMMAND, shell=True) 

不幸的是,Fortran程序與退出。當我在我的殼執行此:

$>/path/to/FORTRAN/program << ! 
>INPUT_FILE1 
>INPUT_FILE2 
>! 

一切正常(無Attempt to read past end of file)。

我無法訪問Fortran源代碼,因此我無法檢查那裏發生了什麼。我認爲這與我通過subprocess調用程序的方式有關 - 我只是無法弄清楚什麼。

我正在使用Python 2.6.6。

快速說明:Fortran程序會提示輸入兩個文件,但它不會將它們識別爲命令行選項(它們不能與調用程序一起提供)。如果你想運行它 - 比如說一個shell腳本(批處理模式) - 你需要捕獲return命令來執行命令,但也要提供這兩個文件。 << !由於缺少更好的術語而打開「列表」。下列命令被傳遞給等待執行的程序,直到輸入!

我已經成功地多次使用這種方法(不同的Fortran代碼),並使用這個方法,使用C shell腳本(不是Python)。

+0

我對從終端運行FORTRAN不夠了解 - << <<的意義是什麼?那是從「標準輸入」還是以其他方式閱讀?也許問題是你提交輸入文件作爲參數,但它期望它將要解析的緩衝區。很難說沒有關於該計劃的更多信息。 –

+0

我試圖通過調用一個轉儲它的標準輸入的小程序進行再現,並且在這種情況下命令行和子進程都可以工作。 –

回答

1

你可以嘗試"\r\n"(TTY行)。

+0

這個工作,稍作修改:我使用''p.communicate(「INPUT_FILE1 \ nINPUT_FILE2」)''沒有''\ r''。正如@ Armin-Rigo所建議的那樣,''communic''和''stdin.write''之間有什麼區別?或者,這是一個相當不同的問題... – Schorsch

+0

在這種情況下,它應該等同於'.stdin.close(); .wait()'。不同之處可能在於最初的'.write()'部分。 – jfs

+0

雖然[看看源代碼,我沒有看到任何區別](http://hg.python.org/cpython/file/2.6/Lib/subprocess.py#l673),除了'bufsize = 1'(行緩衝)和'close_fds = True'(後者應該是posix的默認值) – jfs

1

也許這是由shell調用shell=True引起的,如果在你的系統上沒有調用bash。您可避免因擴展shell語法<<,而是建立在自己的整個調用,如:

popen = subprocess.Popen(["/path/to/FORTRAN/program"], stdin=subprocess.PIPE) 
popen.stdin.write('123\n') 
time.sleep(0.1) # hack, following LAK's suggestion 
popen.stdin.write('456\n') 
popen.stdin.close() 
result = popen.wait() 
+0

問題依然存在。 – Schorsch

+0

我編輯LAK的想法後的代碼。 –

+0

我已經嘗試了您的更新建議 - 並且使用了''sleep''命令 - 沒有成功。現在我通過將命令寫入shell腳本並從Python執行它來修復它。也許有點複雜,但它的工作原理。 – Schorsch

1

我有什麼可能是一個類似的問題而回,並且該解決方案橫空出世加入一個小小的停頓。看看this,看看這種技術是否有幫助。在結束

from subprocess import Popen, PIPE 

p = Popen(["/path/to/FORTRAN/program"], stdin=PIPE, 
      bufsize=1, close_fds=True) 
p.communicate("INPUT_FILE1\r\nINPUT_FILE2") 
rc = p.returncode 

有/無"\r\n"