python子进程终端mac osx

Posted

技术标签:

【中文标题】python子进程终端mac osx【英文标题】:python subprocess terminal mac osx 【发布时间】:2013-07-21 21:08:39 【问题描述】:

长期潜伏者,第一次海报。

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

就我而言,我需要打开一个新的终端窗口,然后将路径发送到特定版本的应用程序,最后是我希望在该应用程序中打开的文件的路径。

我知道如何使用子进程直接调用所需的应用程序(不打开可见终端),如何使用子进程打开一个新终端,以及如何调用应用程序路径或文件路径(无法使用 --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

【问题讨论】:

不幸的是,这并不像您想象的那样容易。终端打开它自己的子进程(例如 bash)并直接与它们通信。向终端的标准输入发送任何内容都不会到达其他进程。您可能错误地处理了这个问题。 感谢 korylprince,我将尝试以不同的方式处理它。感谢您的回复。 【参考方案1】:

@cody

我对你的回答太长了,所以我在做一个回答:

    你是对的,如果你按照你提供的方式输入它,它会标记一个错误,如果你把 -n 放在终端之前它仍然会标记一个错误。但是,如果您按照我在第一个示例中显示的方式输入它(终端后的 -n)“打开”会调用应用程序捆绑终端的新实例,即使一个已经打开。

至于 2-3,这是我的研究让我相信的,但我希望我错了或在某个地方遗漏了什么,这里有人可以澄清一下。可悲的是,我没有弄错……

我可能应该扩展我正在尝试做的事情,因为它可能有助于生成更好的方法来通过 Python 完成它。

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

解析必要的信息、构建命令并启动一个新终端来启动所需的应用程序都是微不足道的。对所需文件执行相同操作也很简单。 The issue arises when a particular version of the app is chosen, and I have not been able to pass the newly birthed instance of Terminal with more than a single command (honestly the syntax of my OSX command may be the issue as well, will post再向下)。

我可以让以下两个命令正常工作:

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】:
    首先,我怀疑您尝试运行的命令是否会运行。 您是否首先在终端中尝试过? open -an Terminal会给你 一个错误。它可能应该类似于open -n /Applications/Utilities/Terminal.app 其次,@korylprince 是对的:open 自己会创建新进程 Terminal 并退出。因此,您将管道与错误的进程相关联。 第三,在将ls 传递给该进程的stdin 的那一刻 不存在(除非您将 -W 选项传递给open, 但由于 2 的问题,它肯定无济于事。

所以我认为只有一个机会可以做到这一点:通过 AppleScript。您可以创建一个 AppleScript 字符串,如下所示:

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

然后通过osascript -e '<your_script>' 通过 Popen 运行此脚本。 是的,这很棘手(我会说这是一个 hack) 是的,将多行字符串传递给 Popen 并确定正确的终端窗口可能会出现问题。 但这是可能的。

【讨论】:

以上是关于python子进程终端mac osx的主要内容,如果未能解决你的问题,请参考以下文章

Python子进程显示在终端上登录并保存在文件中

无法使用python存储子进程的终端输出

通过Python子进程模块(airodump-ng)停止Linux终端中正在运行的进程[重复]

在 Python 子进程模块中过滤掉需要终端的命令

Python 子进程调用返回“找不到命令”,终端正确执行

Python子进程将孩子的输出到文件和终端?