OS X与Python 3:在新终端中执行bash命令的行为?

0 投票
2 回答
622 浏览
提问于 2025-04-17 02:58

我看到过类似的问题(比如 在新的Mac OS X终端窗口中运行命令),但我需要确认这个命令在Mac上的表现(我自己没有Mac)。如果有人能在Python 3的Mac上运行以下代码:

import subprocess, os
def runcom(bashCommand):
     sp = subprocess.Popen(['osascript'], stdin=subprocess.PIPE, stderr=subprocess.PIPE)
     sp.communicate('''tell application "Terminal"\nactivate\ndo script with command "{0} $EXIT"\nend tell'''.format(bashCommand))

runcom('''echo \\"This is a test\\n\\nThis should come two lines later; press any key\\";read throwaway''')
runcom('''echo \\"This is a test\\"\n\necho \\"This should come one line later; press any key\\";read throwaway''')
runcom('''echo \\"This is testing whether I can have you enter your sudo pw on separate terminal\\";sudo ls;\necho \\"You should see your current directory; press any key\\";read throwaway''')

首先,最基本的是,“打开新终端并执行”这个命令正确吗?(为了参考,这个版本的 runcom 函数来自于 下面这个回答,比我原来的版本要干净很多。)

至于实际测试:第一个测试是检查内部双转义的 \\n 字符是否真的有效。第二个测试是看看我们能否在“脚本”中放入(未转义的)换行符,并且它仍然像分号一样工作。最后,最后一个测试是检查是否可以在单独的终端中调用sudo进程(这是我的最终目标)。

在所有情况下,新终端应该在你“按下任意键”后立即消失。请确认这一点。

如果其中有一个不工作,任何修正或诊断都将非常感激。另外,是否有更符合Python风格的方法在Mac上打开终端并执行(sudo,扩展的)bash命令?

谢谢!

2 个回答

1

我没有Python 3,不过我稍微修改了一下你的runcom函数,应该可以正常工作了:

def runcom(bashCommand):
    sp = subprocess.Popen(['osascript'], stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    sp.communicate('''tell application "Terminal"\nactivate\ndo script with command "{0} $EXIT"\nend tell'''.format(bashCommand))
1

[...] 它的预期行为 [...]

这个问题不好回答,因为这些命令的表现是我预期的,但可能和你预期的不一样。

关于实际的测试:第一个测试是检查内部的双转义的 \n 字符是否真的有效。

这个 \\n 用两个反斜杠确实能正常工作,它会让 echo 输出一个换行符。不过,echo 不会输出双引号。

第二个测试是看看我们能否在“脚本”中放入(未转义的)换行符,并且它的工作方式和分号一样。

这个也能正常工作。

最后,最后一个测试是看看能否在一个单独的终端中调用一个 sudo 进程(这是我的最终目标)。

没有理由这个不行,实际上它是可以的。

在所有情况下,新的终端应该在你“按下任意键”后消失。请确认这一点。

这不会工作,原因有几个:

  • read 在 bash 中默认会读取整行,而不是一个字符
  • 在你提供的脚本执行完后,终端中的 shell 没有理由退出
  • 即使 shell 退出,用户也可以设置 Terminal.app 不在 shell 退出后关闭窗口(这甚至是默认设置)

其他问题:

  • 你提供给 osascript 的脚本会在执行前出现在终端窗口中。在上面的例子中,用户会看到每个“这是一个测试 [...]”出现两次。
  • 我搞不清楚 $EXIT 是想干什么
  • ls 命令只会在“当前目录”中显示用户的主目录,因为在新的终端窗口中,当前工作目录总是用户的主目录
  • throwaway 在脚本 bashCommand 退出后将不可用

最后,这个脚本在 Python 3 下根本无法工作,因为它会崩溃并显示 TypeErrorcommunicate() 需要一个字节字符串作为参数,而不是普通字符串。

另外,想知道有没有更符合 Python 风格的方法来在 Mac 上打开终端 [...]

你可以看看 PyObjC!这不一定更符合 Python 风格,但至少可以减少一些间接层。

撰写回答