3

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.

6
  • What is the reason for usin stdout=PIPE if the program is expected to survive your script? Commented Mar 11, 2022 at 14:22
  • @SergeBallesta It's here, because I tried any solution I was able to find, without it it also didn't work as desired. Commented Mar 11, 2022 at 14:25
  • 1
    It is weird. I have just tried this code with notepad.exe (I do not use discord), and the notepad window stays correctly opened after the end of the Python script. Could you try using notepad to make sure whether the problem is related to your Python installation or to discord. Commented Mar 11, 2022 at 14:32
  • subprocess.Popen(['notepad.exe']) seems to work in that notepad remains open after the script has terminated. Commented Mar 11, 2022 at 14:39
  • @SergeBallesta @JonSG I updated my question. subprocess.Popen(['notepad.exe']) didn't work for me, but with calc.exe it did. Commented Mar 11, 2022 at 14:50

5 Answers 5

5

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")
Sign up to request clarification or add additional context in comments.

6 Comments

@Karol if this answer helped you or you like it, please do not forget to vote up and mark the answer as a solution, I would really appreciate it.
I'm sorry, but... your solution also didn't work 😅. I tested for both Slack and Discord. Both programs closed after sleep(5)
Whatever the function used to start a new process, be it os.system, os.spawn, or subprocess.*, the new process will be a direct child of the Python interpretor, and in the Windows OS, it will be created via CreateProcess. On a Unix or Unix-like system it would be created via fork and exec. So unsure whether it could be useful for OP, but the first sentence is wrong.
@KarolZlot try os.execl if you don't need to do anything in python after the new process is started
@0dminnimda I need to run a few programs like this and only then quit python script. However os.execl() seems to exit python script immediately.
|
4

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

Comments

2

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)

3 Comments

It also didn't work :) But thank you for trying.
You can try many other programs, like notepad.exe or winver
It works after all. See "Update 3" in question.
1

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

5 Comments

@KarolZlot posting the second answer as it's a different approach and edititng the first one doesn't work for me because of the comments, but now this should work, I tested it!
I just tested it and... it still doesn't work 😭.
But all the time I was testing from vscode (F5). When I now tried running from PowerShell, then it started working as desired (I see that other answers also work.... 🤦)
It works after all. See "Update 3" in question.
@KarolZlot it'll be really nice if you'd accepted the best answers a solution. As it seems os.popen is the most elegant way ;3
0

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

2 Comments

this executes the command in the subshell and this is also blocking function, meaning python script won't be able to do anything but wait until the process is ended
As @0dminnimda said, it isn't working as desired.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.