如何启动另一个程序并在 Python 脚本完成后保持它 运行?

How to start another program and keep it running after Python script finishes?

我的问题与 类似,但是 none 列出的答案对我有用。

我尝试 运行 一个程序,例如 Slack 或 Discord(或问题更新中列出的其他程序)。即使我的脚本完成,我也希望程序 运行。

我需要这个才能在 Windows 上工作。

注意:仅当从 Python 脚本启动 Slack / Discord 时才会出现此问题,如果之前是 运行ning,则不会关闭。

示例代码:(如您所见,我尝试了多种方法):

import os, subprocess
from time import sleep
from subprocess import Popen, PIPE, STDOUT

# discord_path=r"C:\Program Files\Discord\Discord.exe"
# discord_path2=r"C:\Users\user\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Discord Inc\Discord.lnk"
# os.startfile(discord_path2)

# subprocess.run([r"C:\Users\user\AppData\Local\Discord\Update.exe", "--processStart", "Discord.exe"],shell=True)
# subprocess.Popen([r"C:\Users\user\AppData\Local\Discord\Update.exe", "--processStart", "Discord.exe"],shell=True)
# subprocess.call([r"C:\Users\user\AppData\Local\Discord\Update.exe", "--processStart", "Discord.exe"])
# subprocess.Popen([r"C:\Users\user\AppData\Local\Discord\Update.exe", "--processStart", "Discord.exe"], stdin=None, stdout=None, stderr=None, close_fds=True)

# slack_path2=r"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Slack Technologies Inc\Slack.lnk"
# os.startfile(slack_path2)
#  stdin=None, stdout=None, stderr=None, 

# subprocess.Popen([r"C:\Program Files\Slack\slack.exe", "--startup"], close_fds=True)

proc = Popen([r"C:\Program Files\Slack\slack.exe", "--startup"], stdout=PIPE, stderr=STDOUT)

sleep(5)
# now program (Slack / Discord) is exited and I can't prevent it

更新: 我还测试了 notepad.execalc.exewinver.

notepad.exewinver 的行为与 Slack 和 Discord 相同。 但是 calc.exe 在脚本完成后保持打开状态(因此该程序表现异常)。

代码:

subprocess.Popen(['notepad.exe'])
subprocess.Popen(['calc.exe'])
subprocess.Popen(['winver'])

更新二: 我需要用这种方式 运行 一些程序(包括 Slack 和 Discord),所以使用 os.execl() 不会完成这项工作,因为它会立即退出 python 脚本。

更新 3: 正如我在其中一条评论中提出的那样,事实证明我是 vscode 中的 运行ning python,而 vscode 在 main Python 之后以某种方式关闭进程脚本完成。 当我从 Powershell 运行 Python 编写脚本时,下面的大多数答案都可以正常工作。

您应该能够运行将程序作为命令而不是子进程。您需要使用 os.system(*your command*) 函数执行命令。您必须使用 import os

导入它

这样它应该单独启动程序而不是在子进程中

您应该使用 os.spawn*() 函数来创建新进程

这是你的例子:

我们 运行 path 处的程序带有非阻塞标志 os.P_NOWAIT

最后两个参数被赋予进程。 (是的,如果您不熟悉,第一个参数应该是调用它的程序的路径,然后是您的参数,以获取更多信息 google 'argv')

import os

path = r"C:\Program Files\Slack\slack.exe"
os.spawnl(os.P_NOWAIT,        # flag
          path,               # programm
          path, "--startup")  # arguments

print("Bye! Now it's your responsibility to close new process :0")

因为我既不使用discord也不使用slack,所以我无法测试任何东西。但是我会尝试使用进程创建标志来打破新进程和 Python 程序之间尽可能多的链接:

from subprocess import Popen, CREATE_NEW_PROCESS_GROUP, DETACHED_PROCESS

proc = Popen([r"C:\Program Files\Slack\slack.exe", "--startup"],
             creationflags=CREATE_NEW_PROCESS_GROUP|DETACHED_PROCESS)

解决方案实际上比看起来更简单:]
我们可以在cmd/pipe中直接使用os.popen到运行命令,这样就可以让那些进程不依赖于python进程! 那么让我们开始吧:

import os

os.popen("notepad.exe")
os.popen("notepad.exe")

print("Bye! Now it's your responsibility to close new process(es) :0")

this 是我的灵感来源,但这个解决方案的工作方式略有不同


Windows-only:

此外,如果您不想 运行 多个 Popen(通过 os.popen)打开一个 cmd.exe 并改为使用它:

import subprocess
from time import sleep

path = r"C:\Windows\System32\cmd.exe"
p = subprocess.Popen(
    [path],
    bufsize=-1,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    stdin=subprocess.PIPE)


def comunicate(process, message):
    process.stdin.write(message)
    process.stdin.flush()


comunicate(p, b'notepad.exe\n')
comunicate(p, b'notepad.exe\n')

sleep(0.1)
comunicate(p, b'exit\n')  # closes cmd

print("Bye! Now it's your responsibility to close new process :0")

事实证明,我只需要 运行 Python 脚本,而不是来自 vscode,例如来自 Powershell。