2

我知道已经发布了类似的问题,但我见过的方法似乎都不起作用。我想在 mac 上使用 python 子进程启动应用程序 xfoil,并使用脚本发送 xfoil 一堆命令(xfoil 是一个在终端窗口中运行的应用程序,您可以通过文本命令与之交互)。我可以使用脚本启动 xfoil,但我似乎不知道如何向它发送命令。这是我目前正在尝试的代码:

import subprocess as sp

xfoil = sp.Popen(['open', '-a', '/Applications/Xfoil.app/Contents/MacOS/Xfoil'], stdin=sp.PIPE, stdout=sp.PIPE)

stdout_data = xfoil.communicate(input='NACA 0012')

我也试过

xfoil.stdin.write('NACA 0012\n')

为了向 xfoil 发送命令。

4

1 回答 1

3

正如手册页所说,

open命令打开一个文件(或目录或 URL),就像您双击文件的图标一样。

最终,应用程序由 LaunchServices 启动,但这并不重要——重要的是它不是您的 shell 或 Python 脚本的子级。

此外,它的全部意义open在于打开应用程序本身,因此您不必深入研究它并找到 Unix 可执行文件。如果您已经拥有它,并且想将其作为 Unix 可执行文件运行……只需运行它:

xfoil = sp.Popen(['/Applications/Xfoil.app/Contents/MacOS/Xfoil'], stdin=sp.PIPE, stdout=sp.PIPE)

事实证明,在这种情况下,MacOS/Xfoil甚至不是正确的程序。它显然是某种包装器Resources/xfoil,它实际上等同于您/usr/local/bin/xfoil在 linux 上得到的东西。所以你想这样做:

xfoil = sp.Popen(['/Applications/Xfoil.app/Contents/Resouces/xfoil'], stdin=sp.PIPE, stdout=sp.PIPE)

(此外,从技术上讲,您的命令行甚至根本不应该工作;-a指定一个应用程序,而不是 Unix 可执行文件,并且您应该传递至少一个文件来打开。但是因为 LaunchServices 可以启动 Unix 可执行文件,就好像它们一样是应用程序,并且open不检查参数是否有效,open -a /Applications/Xfoil.app/Contents/MacOS/Xfoil最终会有效地做与 .) 相同的事情open /Applications/Xfoil.app/Contents/MacOS/Xfoil。)


为了未来读者的利益,我将在评论中包含以下信息:

If you just write a line to stdin and then return from the function/fall off the end of the main script/etc., the Popen object will get garbage collected, closing both of its pipes. If xfoil hasn't finished running yet, it will get an error the next time it tries to write any output, and apparently it handles this by printing Fortran runtime error: end of file (to stderr?) and bailing. You need to call xfoil.wait() (or something else that implicitly waits) to prevent this from happening.

于 2013-02-21T19:33:21.133 回答