Python子进程终端Mac OSX

4

很久以前我就开始潜水了,第一次发帖。

我知道在互联网上有很多关于使用subprocess的例子,但是我还没有找到一个能够解释我需要采取哪些步骤来打开一个新的终端窗口并发送命令的例子。有很多帖子提供了通过直接调用subprocess来启动工具和脚本的解决办法,但是我没有找到一个能够真正回答如何正确地将命令发送到终端的原始问题的帖子。

在我的情况下,我需要打开一个新的终端窗口,然后发送一个特定版本应用程序的路径,最后再发送我想要在该应用程序中打开的文件路径。

我知道如何使用subprocess直接调用所需的应用程序(而不打开可见的终端),如何使用subprocess打开一个新的终端,并如何调用应用程序路径或文件路径(尝试使用--args for open()或其他解决方案无法同时执行两者)。

我无法在打开终端后向终端发送命令。以下是打开终端的简单示例并发送ls命令,但它不起作用。

from subprocess import Popen, PIPE, STDOUT

p = Popen(['open', '-a', 'Terminal', '-n'], stdout=PIPE, stdin=PIPE, stderr=STDOUT)

output = p.communicate(input='ls')
print(output)

这很可能是一个微不足道的问题,我可能只是遗漏了某些东西,但我一直没能找到需要的信息或示例,这让我感到非常沮丧,所以我想寻求帮助。
非常感谢任何帮助!TIA

1
很不幸,这并不像你想的那样容易。终端打开了它自己的子进程(例如bash)并直接与它们通信。将任何内容发送到终端的标准输入并不能传递给其他进程。你可能正在错误地解决这个问题。 - korylprince
谢谢korylprince,我打算尝试不同的方法。感谢您的回复。 - Glenn
2个回答

3

@cody

你对我的回答做出了正确的指正。如果按照你提供的方式输入命令,会出现错误提示,如果把-n放在Terminal前面也会出现错误提示。然而,如果按照我在第一个示例中展示的方式输入命令(-n放在Terminal后面),即使已经有一个应用程序捆绑包终端已经打开,“open”命令也会调用终端的新实例。

至于2-3,我的研究也是这个方向。但愿我错了或错过了什么地方,这里的某个人可以帮助澄清。不幸的是,我没有弄错……

我可能需要扩展一下我的目的,因为这可能有助于通过Python更好地实现它。

我创建了一个工具,根据艺术家正在处理的电影、场景和镜头启动应用程序文件。对于一些应用程序,如Nuke和Houdini,从Terminal启动可以获得大量信息,否则艺术家将无法看到这些信息,因此我们希望给艺术家提供在终端中启动他们选择的文件的选项。该终端必须是独立的,必须是一个新的终端实例,因为我创建的应用程序必须在启动后持续存在,以便在不同的应用程序中打开其他镜头,而不必让用户经常打开该应用程序。

解析所需信息、构建命令并启动启动所需应用程序的新终端都是微不足道的。同样地,使用所需文件也很微不足道。问题出现在选择特定版本的应用程序时,我无法将新创建的终端实例传递给多个命令(如果说我的OSX命令语法可能也有问题,将此贴下方)。

我可以轻松执行以下两个命令:

p = Popen(['open', '-a', 'Terminal', '-n', '--args', '/Applications/Nuke6.3v8/Nuke6.3v8.app/Nuke6.3v8'])

p = Popen(['open', '-a', 'Terminal', '-n', '--args', '/Path/to/Nuke/File.nk'])  

我无法使以下内容正常工作:
p = Popen(['open', '-a', 'Terminal', '-n', '--args', '/Applications/Nuke6.3v8/Nuke6.3v8.app/Nuke6.3v8', '/Path/to/Nuke/File.nk'])

我的想法可能是在Popen中启动终端,然后传递我需要的命令。但这行不通,然后我来到了这里哈哈。

再次感谢任何帮助!知道我不能将所需的命令发送到终端,这为我节省了大量时间,原本会花费在持续沮丧的研究上。


2
  1. 首先,我怀疑你尝试运行的命令根本无法运行。你在终端中尝试过吗?open -an Terminal会给你一个错误。它可能应该是类似于open -n /Applications/Utilities/Terminal.app这样的东西。
  2. 其次,@korylprince是对的:open本身将创建新的Terminal进程并退出。所以你正在将管道与错误的进程链接。
  3. 第三,在将ls传递到stdin的那个进程不存在(除非你将-W选项传递给open,但由于第二个问题,它肯定不会有帮助)。

因此,我只看到一种机会来做到这一点:通过AppleScript。你可以创建一个AppleScript字符串,类似于下面的内容:

tell application "System Events"
    tell process "Terminal"
        keystroke "ls"
        keystroke return
    end tell
end tell

然后通过Popen运行此脚本,命令如下:osascript -e '<your_script>'

是的,这很棘手(我会说这是一种黑客技巧)
是的,可能会遇到将多行字符串传递给Popen以及确定正确的终端窗口的问题。
但这是可能的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接