【问题标题】:Execute terminal command from python in new terminal window?在新的终端窗口中从 python 执行终端命令?
【发布时间】:2013-10-18 23:02:04
【问题描述】:

这里的目标是在新的 shell 中运行新的 python 文件,并在现有的 shell 中运行现有的 python 文件。假设我有两个文件,aaa.py 和 bbb.py。为简单起见,aaa.py 所做的只是......

subprocess.call('python bbb.py', shell=True)

...让我们说 bbb.py 确实是...

print 'It worked'

现在的目标是在终端 1 中运行 aaa.py 并让它在终端 2 中启动 bbb.py。我希望存在类似以下命令的内容,但无法弄清楚。

subprocess.call_in_new_window('python bb.py', shell=True)

【问题讨论】:

标签: python shell terminal subprocess new-window


【解决方案1】:

这可能应该是一个评论,但因为我还不能......

在 Windows 中,您可以这样做:

subprocess.call('python bb.py', creationflags=subprocess.CREATE_NEW_CONSOLE)

【讨论】:

  • 有没有办法让终端窗口持久化,这样命令完成后它就不会关闭?
  • import os ; os.system('start cmd /K python bb.py') ... 执行 /c 而不是 /K 会在完成后杀死新窗口。
  • 请为linux用户指定一个命令
【解决方案2】:

通常没有办法从 shell 中执行此操作。您需要做的是运行终端程序本身,或一些为您执行此操作的启动程序。而且每个终端程序的实现方式都不同。

在某些情况下,os.startfile 会做你想做的事,但这不会是通用的。

另外,请注意,一般来说,您实际上需要脚本的绝对路径,因为新的终端窗口将运行新的 shell,因此不一定有相同的工作目录。但是对于示例,我将忽略这一点。


使用 Windows cmd,最简单的方法是使用 start shell 命令。如果你start 是任何命令行程序,包括python,它将获得一个新的cmd 窗口。所以,像:

subprocess.call('start /wait python bb.py', shell=True)

OS X 有一个类似的命令,open。它是一个真正的程序而不是一个 shell 命令,所以你不需要shell=True。但是,使用open 运行命令行程序或脚本通常不会打开新的终端窗口。事实上,它的全部意义在于允许您运行程序,就好像它们在 Finder 中被双击一样,除非它是一个 .command 文件,否则它永远不会在终端中运行任何东西。

因此,您可以创建一个临时的 .command 包装文件和 open ;像这样的东西(未经测试):

with tempfile.NamedTemporaryFile(suffix='.command') as f:
    f.write('#!/bin/sh\npython bb.py\n')
    subprocess.call(['open', '-W', f.name])

或者,您可以明确告诉open 使用 Terminal.app,如下所示:

subprocess.call(['open', '-W', '-a', 'Terminal.app', 'python', '--args', 'bb.py'])

或者您可以通过 AppleEvents 编写 Terminal.app 脚本。例如:

appscript.app('Terminal').do_script('python bb.py')

“执行脚本”事件打开一个新窗口并将其参数作为命令运行。如果您想要更详细的控制,请在 AppleScript 编辑器中打开脚本字典,看看您可以做的所有有趣的事情。


在 Linux 或其他 *nix 系统上……嗯,有 65,102 种不同的桌面环境、启动器和终端程序。您需要处理所有这些吗?

使用 gnome-terminal,再次运行终端会给你一个新窗口,-x 参数可以让你指定一个初始命令,所以:

subprocess.call(['gnome-terminal', '-x', 'python bb.py'])

许多旧终端尝试与xterm 兼容,这与-e 做同样的事情,所以:

subprocess.call(['xterm', '-e', 'python bb.py'])
subprocess.call(['rxvt', '-e', 'python bb.py'])

……等等

您如何知道用户正在使用哪个终端?好问题。您可以从自己那里走类似父进程,直到找到看起来像终端的东西。或者你可以假设每个人都有xterm。或者您可以查看各种发行版如何配置默认终端并搜索所有这些。或者……

【讨论】:

  • 在 OS X 中,'--args' 用作 Terminal.app 的参数,而不是命令行应用程序(在这种情况下是 python)。因此,在这种情况下,subprocess.call 会启动一个运行 python 的终端应用程序(忽略参数)。我目前的解决方法是使用命令行和 args 创建一个临时 .sh 脚本,并将该脚本作为 subprocess.call() 中的参数启动...有点蹩脚,但我想不出更好的方法。
  • 很好的答案,但我想知道您是否知道如何在无头 linux(例如 AWS ubuntu 实例)上完成此操作(运行多个终端)?我有一个启动其他脚本的脚本,但是“gnome-terminal”参数把它搞砸了,因为无头服务器没有安装任何这样的 GUI 终端。
  • 帮了我很多。现在我尝试再次关闭终端,但这更加困难。我似乎无法终止该进程。如果您可以通过有关如何关闭终端的说明来扩展您的答案,那就太好了。
  • 我唯一的评论是对于 Windows,使用表单:subprocess.call('start "" {}'.format(cmd), shell=True) 给了我最好的结果。
  • 有什么办法让终端窗口在运行完成后保持打开状态? (即返回到闪烁的光标命令行)
【解决方案3】:

你将无法做到这一点,至少不像你想的那么简单。由于“终端窗口”,我怀疑您在谈论 Mac。

您也许可以使用 X Window 系统来实现它,但您需要设置很多东西、X 服务器、权限等才能实现它。

如今,此类事情通常会违反正常的安全边界。假设您下载了一个按照您的建议运行的程序。它会打开一个窗口(终端)(对您不可见),它具有与您相同的权限。它继续读取您的所有目录和文件并将它们发送给程序的发起者。你可能对此不满意。在整个过程中,您认为自己在玩游戏,然后退出,第二个 shell 继续运行。

Windows 和 shell 有点脱节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-02
    • 2020-05-14
    • 2022-06-10
    • 2023-04-04
    • 2019-08-20
    • 2019-10-26
    • 2013-12-25
    相关资源
    最近更新 更多