【问题标题】:Python subprocess not executing program correctlyPython子进程未正确执行程序
【发布时间】:2013-03-28 20:43:25
【问题描述】:

我正在尝试在 Python 的 shell 中执行 Fortran 程序。 我使用subprocess 调用Fortran 程序并传递参数(需要两个输入文件)。我就是这样做的:

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

不幸的是,Fortran 程序退出:

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

不是输入文件或 Fortran 程序的问题。当我在我的 shell 中执行此操作时:

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

一切都按预期工作(没有Attempt to read past end of file)。

我无权访问 Fortran 源代码,因此无法检查其中发生了什么。我认为这与我通过 subprocess 调用程序的方式有关 - 我只是不知道是什么。

我使用的是 Python 2.6.6。

快速解释:Fortran 程序将提示输入两个输入文件,但它不会将它们识别为命令行选项(它们不能随程序调用一起提供)。如果你想运行它——比如说一个 shell 脚本(批处理模式)——你需要捕获返回命令来执行命令,还要提供这两个文件。 &lt;&lt; ! 打开一个“列表”,因为没有更好的术语。以下命令被传递给程序,该程序等待执行,直到输入!

我已经多次成功地使用了这种方法(不同的 Fortran 代码),并且在这个方法中,使用了 C shell 脚本(不是 Python)。

【问题讨论】:

  • 我对从终端运行 FORTRAN 知之甚少 - &lt;&lt; 的意义是什么?那是来自stdin 还是其他地方?也许问题在于您将输入文件作为参数提交,但它期望它会解析一个缓冲区。如果没有有关该程序的更多信息,很难说。
  • 我试图通过调用一个转储其标准输入的小程序来重现,并且在这种情况下命令行和subprocess 都可以工作。

标签: python subprocess


【解决方案1】:

你可以试试"\r\n"(tty 换行):

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"

【讨论】:

  • 这行得通,稍作修改:我使用了p.communicate("INPUT_FILE1\nINPUT_FILE2"),没有\r。 @Armin-Rigo 建议的 communicatestdin.write 有什么区别?或者这是一个不同的问题......
  • 在这种情况下,它应该等同于.stdin.close(); .wait()。不同之处可能在于最初的.write() 部分。
  • 虽然looking at the source I don't see any difference 除了bufsize=1(行缓冲)和close_fds=True(后者应该是posix的默认值)
【解决方案2】:

不久前我遇到了类似的问题,结果证明是添加了一个小暂停。看看this,看看该技术是否有帮助。

【讨论】:

    【解决方案3】:

    这可能是由使用shell=True 调用的shell 引起的,如果它没有在您的系统上调用bash。您可以避免依赖扩展的 shell 语法 &lt;&lt;,而是自行构建整个调用,如下所示:

    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()
    

    【讨论】:

    • 我已经尝试了您更新的建议 - 并稍微使用了 sleep 命令 - 没有成功。现在我通过将命令写入 shell 脚本并从 Python 执行它来修复它。也许有点令人费解,但它确实有效。
    猜你喜欢
    • 2014-08-20
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 2012-10-15
    • 1970-01-01
    • 2015-11-10
    • 2018-03-28
    • 1970-01-01
    相关资源
    最近更新 更多