Home > Back-end >  How to start another program and keep it running after Python script finishes?
How to start another program and keep it running after Python script finishes?

Time:03-12

My issue is similar to How to run Python's subprocess and leave it in background , however none of answers listed there worked for me.

I try to run a program, for example Slack or Discord (or other programs listed in question updates). I want program to run even if my script finishes.

I need this to work on Windows.

Note: the issue happen only when Slack / Discord is started from Python script, if it was running before, then it isn't closed.

Example code: (as you can see I tried multiple ways):

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

Update: I tested also notepad.exe, calc.exe and winver.

notepad.exe and winver behave the same as Slack and Discord. However calc.exe stays opened after script finishes (so this program is behaves exceptional).

Code:

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

Update 2: I need to run a few programs this way (including both Slack and Discord), so using os.execl() won't do the job, because it quits python script immediately.

Update 3: As I put in one of comments, it turned out that I was running python from within vscode, and vscode was somehow closing processes after main Python script finished. When I run Python script from Powershell then most answers below work as desired.

CodePudding user response:

You should use os.spawn*() function to create new process

Here's your example:

We run the program at the path with the nonblocking flag os.P_NOWAIT

The last two arguments are given to the process. (yeah, if you're not familiar, the first argument should be the path of the program, by which it's called, and then your arguments, for more info 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")

CodePudding user response:

The solution is actually easier then it seemed :]
We can just use os.popen to run command in cmd/pipe, this will make those processes not dependent on the python process! So let's just do it:

import os

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

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

this served as my inspiration, tho this solution works a little differently


Windows-only:

Also if you don't want to run several Popen's (through os.popen) to open one cmd.exe and use it instead:

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")

CodePudding user response:

As I use neither discord not slack I could not test anything. But I would try to use the process creation flags to break as many links as possible between the new process and the Python program:

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)

CodePudding user response:

you should be able to run the program as a command and not a subprocess. you'll need to excecute a command using the os.system(*your command*) function. you'll have to import it with import os

That way it should launch the program seperate and not in a subprocess

CodePudding user response:

It turned out that I just needed to run Python script not from vscode, but for example from Powershell.

  • Related