18

I want a script to start a new process, such that the new process continues running after the initial script exits. I expected that I could use multiprocessing.Process to start a new process, and set daemon=True so that the main script may exit while the created process continues running.

But it seems that the second process is silently terminated when the main script exits. Is this expected behavior, or am I doing something wrong?

tshepang
  • 12,111
  • 21
  • 91
  • 136
JacquesB
  • 41,662
  • 13
  • 71
  • 86

6 Answers6

16

From the Python docs:

When a process exits, it attempts to terminate all of its daemonic child processes.

This is the expected behavior.

Justin Ardini
  • 9,768
  • 2
  • 39
  • 46
16

If you are on a unix system, you could use os.fork:

import os
import time

pid=os.fork()
if pid:
    # parent
    while True:
        print("I'm the parent")
        time.sleep(0.5)    
else:
    # child
    while True:
        print("I'm just a child")
        time.sleep(0.5)

Running this creates two processes. You can kill the parent without killing the child. For example, when you run script you'll see something like:

% script.py
I'm the parent
I'm just a child
I'm the parent
I'm just a child
...

Stop the script with ctrl-Z:

^Z
[1]+  Stopped                 script.py

Find the process ID number for the parent. It will be the smaller of the two process ID numbers since the parent came first:

% ps axuw | grep script.py
unutbu    6826  0.1  0.1  33792  6388 pts/24   T    15:09   0:00 python /home/unutbu/pybin/script.py
unutbu    6827  0.0  0.1  33792  4352 pts/24   T    15:09   0:00 python /home/unutbu/pybin/script.py
unutbu    6832  0.0  0.0  17472   952 pts/24   S+   15:09   0:00 grep --color=auto script.py

Kill the parent process:

% kill 6826

Restore script.py to the foreground:

% fg
script.py
Terminated

You'll see the child process is still running:

% I'm just a child
I'm just a child
I'm just a child
...

Kill the child (in a new terminal) with

% kill 6827
unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • "You can kill the parent without killing the child.". How? – Martin Thoma Aug 21 '17 at 19:00
  • @MartinThoma: I added details on how to do that from the terminal above. Many OSes have a GUI process monitor which can make this even easier, but those details would be OS/GUI specific. – unutbu Aug 21 '17 at 19:15
  • It doesn't print from the child process, only the parent one. – nerdguy Jun 29 '19 at 15:53
12

Simply use the subprocess module:

import subprocess
subprocess.Popen(["sleep", "60"])
Philipp
  • 48,066
  • 12
  • 84
  • 109
1

Here is a related question on SO, where one of the answers gives a nice solution to this problem:

"spawning process from python"

Community
  • 1
  • 1
Pontus
  • 1,639
  • 2
  • 11
  • 6
0

If you are on a unix system (using docs):

#!/usr/bin/env python3
import os
import sys
import time
import subprocess
import multiprocessing
from multiprocessing import Process

def to_use_in_separate_process(*args):
    print(args)

    #check args before using them:
    if len(args)>1:
        subprocess.call((args[0], args[1]))
        print('subprocess called')

def main(apathtofile):
    print('checking os')
    if os.name == 'posix':
        print('os is posix')
        multiprocessing.get_context('fork')
        p = Process(target=to_use_in_separate_process, args=('xdg-open', apathtofile))
        p.run()
    print('exiting def main')

if __name__ == '__main__':
    #parameter [1] must be some file that can be opened by xdg-open that this
    #program uses.
    if len(sys.argv)>1:
        main(sys.argv[1])
        print('we can exit now.')
    else:
        print('no parameters...')
    print('mother program will end now!')
    sys.exit(0)
ilias iliadis
  • 601
  • 8
  • 15
0

In Ubuntu the following commands keep working even though the python app exit.

url = "https://www.youtube.com/watch?v=t3kcqTE6x4A"  
cmd = f"mpv '{url}' && zenity --info --text 'you have watched {url}' &"
os.system(cmd)
podcast
  • 131
  • 7