【问题标题】:launch external shell python instance in shell from python从 python 在 shell 中启动外部 shell python 实例
【发布时间】:2014-02-04 16:41:51
【问题描述】:

我想从 python 脚本中调用一个单独的非子 python 程序,并让它在新的 shell 实例中外部运行。原始的 python 脚本不需要知道它启动的实例,它不应该在启动的进程运行时阻塞,也不应该关心它是否死亡。这是我尝试过的,它没有返回错误,但似乎什么也没做......

import subprocess

python_path = '/usr/bin/python'

args = [python_path, '&']

p =  subprocess.Popen(args, shell=True)

我应该做些什么不同

编辑

这样做的原因是我有一个内置 python 版本的应用程序,我已经编写了一些 python 工具,应该与这个应用程序一起单独运行,但不能保证用户会在他们的系统上安装 python在我正在使用的内置版本的应用程序之外。因此,我可以通过编程方式从内置版本中获取 python 二进制路径,并且我想启动内置 python 的外部版本。这消除了用户自己安装 python 的需要。所以本质上我需要一种简单的方法来使用我当前运行的python版本以编程方式调用外部python脚本。

我不需要将任何输出捕获到原始程序中,实际上一旦启动我希望它与原始程序无关

编辑 2

所以看来我最初的问题很不清楚,所以这里有更多细节,我想我试图过度简化问题:

我正在运行 OSX,但代码也应该可以在 Windows 机器上运行。

具有内置 CPython 版本的主应用程序是一个已编译的 C++ 应用程序,它附带一个在运行时使用的 Python 框架。您可以通过在 OSX 上的终端窗口中执行此操作来启动此版本 python 的嵌入式版本

/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python

从我的主应用程序中,我希望能够在嵌入在主应用程序中的 python 版本中运行一个命令,该命令使用上述 python 版本启动 python 脚本的外部副本,就像我这样做一样在终端窗口中执行以下命令。新启动的孤立进程应该有自己的终端窗口,以便用户可以与之交互。

/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python my_python_script

我希望子 python 实例不要阻塞主应用程序,并且我希望它有自己的终端窗口,以便用户可以与之交互。一旦以任何方式启动,主应用程序不需要知道孩子。我这样做的唯一原因是使用终端为用户自动启动外部应用程序

【问题讨论】:

  • 你这样做是为了什么?如果你解释了这一点,那么解释如何做你真正想做的事情会更容易。
  • 附带说明,“以编程方式从内置版本获取 python 二进制路径”的方法是 sys.executable
  • @abarnert 我实际上试过了,但在这种情况下它并不那么简单,因为 python 嵌入到另一个应用程序中,这个命令返回到“主”进程的路径,在这种情况下不是一个python实例
  • 您的编辑 still 并没有说您要运行 一个新的终端窗口,然后在该窗口内运行 Python。由于这就是问题的全部重点,而且问题中的任何地方都没有提到它,因此您需要再次对其进行编辑。
  • 如果您实际运行嵌入在其他 C 程序中的 Python,则可能没有 Python 可执行文件,或者它可能无法正常工作。如果你只关心一个特定的应用程序,它恰好有一个可用的普通 Python 可执行文件,那很好......

标签: python shell popen


【解决方案1】:

您可以尝试使用screen 命令

使用此命令创建一个新的 shell 实例,当前实例在后台运行。

# screen; python script1.py

运行上述命令后,将看到一个新的 shell 提示符,我们可以在其中运行另一个脚本,并且 script1.py 将在后台运行。

希望对你有帮助。

【讨论】:

    【解决方案2】:

    其实我认为你的问题可能有解决方案,我在另一个问题here 找到了一个有用的解决方案。 这样 subprocess.popen 会启动一个新的 python shell 实例并从那里运行第二个脚本。它在 Windows 10 上非常适合我。

    【讨论】:

      【解决方案3】:

      如果您尝试启动一个新的终端窗口以在其中运行一个新的 Python(这不是您的问题所要求的,但从评论中听起来这就是您真正想要的):

      你不能。至少不是以通用的跨平台方式。

      Python 只是一个命令行程序,可以使用它给出的任何 stdin/stdout/stderr 运行。如果这些恰好来自终端,那么它正在终端中运行。除此之外,它对终端一无所知。

      如果您需要为某些特定平台和某些特定终端程序执行此操作,例如 OS X 上的 Terminal.app、OS X 上的 iTerm、Windows 上的“DOS 提示符”、任何 X11 系统上的 gnome-terminal 等.—这通常是可行的,但方法是启动或编写终端程序脚本并告诉它打开一个新窗口并在该窗口中运行 Python。而且,不用说,他们都有完全不同的方法。

      即便如此,也并非在所有情况下都是可能的。例如,如果您通过 ssh 连接到远程机器并在该机器上运行 Python,它就无法返回到您的机器并打开一个新的终端窗口。

      在大多数具有多个可能终端的平台上,您可以编写一些启发式代码来确定您当前在哪个终端下运行,只需步行 os.getppid() 直到找到看起来像您知道如何处理的终端(如果你到达init/launchd/etc 却没有找到一个,那么你就没有在终端中运行)。

      【讨论】:

      • 有什么方法可以使用os.startfile吗?
      • @mhlester:由于该功能只存在于 Windows 上,显然没有跨平台的解决方案使用它……
      • @mhlester:鉴于 OP 正在尝试使用 Unix 样式的 shell 语法,我怀疑他不在 Windows 上。但我可能错了……
      • 甚至没有意识到这是仅限 Windows。我在面向用户的前端的 python 体验只有 Windows。我现在就闭嘴:)
      • 我想您可以尝试在与第二个进程通信的第三个 python 进程中在 python 中创建自己的终端仿真器窗口,从而实现跨平台。但我怀疑很多人真的想这样做。
      【解决方案4】:

      问题是您正在使用参数& 运行Python。 Python 不知道该怎么做。就像在 shell 中输入这个:

      /usr/bin/python '&'
      

      事实上,如果你注意,你几乎肯定会通过你的 stderr 得到类似的东西:

      python: can't open file '&': [Errno 2] No such file or directory
      

      ...这正是您在 shell 中执行等效操作所获得的结果。

      你可能想要的是相当于 this shell 命令:

      /usr/bin/python &
      

      但是& 根本没有参数,它是 sh 语法的一部分。 subprocess 模块对 sh 语法一无所知,并且您告诉它不要使用 shell,因此没有人可以解释 &

      可以告诉subprocess 使用shell,这样它就可以为您执行此操作:

      cmdline = '{} &'.format(python_path)
      p = subprocess.Popen(cmdline, shell=True)
      

      但实际上,没有充分的理由这样做。只需打开一个子进程而不是在其上调用communicatewait已经有效地“将其置于后台”,就像& 在shell 上所做的那样。所以:

      args = [python_path]
      p = subprocess.Popen(args)
      

      这将启动一个新的 Python 解释器,该解释器在后台运行,尝试使用与父级相同的 stdin/stdout/stderr。我不知道你为什么要这样做,但在 shell 中使用 & 是一样的。

      【讨论】:

      • 我相信(我想自己就在昨天这样做)OP希望在自己的窗口中启动一个新的shell,并使用它自己的输出。我会发布一个答案,但也无法弄清楚。
      • @mhlester 这正是我想要的行为
      • @jonathantopf:那你为什么要使用&?为什么你没有在问题的任何地方说想要一个新的终端窗口?
      • 标题中的“launch external shell python”是我的线索
      • @abarnert 抱歉,如果问题含糊不清,我希望编辑能增加一些清晰度
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-16
      • 1970-01-01
      • 2019-05-10
      • 2023-04-07
      • 2018-10-15
      • 2017-04-11
      相关资源
      最近更新 更多