0

I start this program all.py

import subprocess
import os

scripts_to_run = ['AppFlatForRent.py','AppForSale.py','CommercialForSale.py','LandForSale.py','MultipleUnitsForSale.py','RentalWanted.py','RentCommercial.py','RoomsForRent.py','RoomsWanted.py','ShortTermDaily.py','ShortTermMonthly.py','VillaHouseForRent.py','VillaHouseForSale.py']


for s in scripts_to_run:
    subprocess.Popen(["python", os.path.join(os.getcwd(), s)])

Its running 13 programs at a time. The problem is that in the sublime - unlike other programs- this particular program doesnt cancel the built. it just keep running (I know because the program is inputting values in the database and it doesnt stop doing that)

I want it to be done via terminal.

any help?

user3265370
  • 121
  • 1
  • 2
  • 12
  • This probably depends on the implementations of scripts_to_run. Remove them all and add them one by one to the list, to determinate which one is causing problems. – bosnjak Mar 25 '14 at 11:49
  • related: [How to make child process die after parent exits?](http://stackoverflow.com/q/284325/4279) and [Best way to kill all child processes](http://stackoverflow.com/q/392022/4279) – jfs Mar 25 '14 at 11:50
  • I don't think he wants to kill the children or the main program. He just wants the children to finish executing naturally. – bosnjak Mar 25 '14 at 11:51
  • In that case it is enough to look at `ps -ef | grep python` to see which Python scripts are stuck – jfs Mar 25 '14 at 11:54
  • i just want to be able to stop all.py to stop executing after its started. it just simply doesnt stop building. the stop building option in this program is not offered by sublime, unlike other programs – user3265370 Mar 25 '14 at 11:58
  • Thanks @J.F.Sebastian. Can you tell me how can i kill the process then? – user3265370 Mar 25 '14 at 12:02
  • do you want to kill all child Python scripts after a timeout? – jfs Mar 25 '14 at 12:07
  • yes. all.py is running 12 other programs within it. i want to stop all while they are running – user3265370 Mar 25 '14 at 12:22

2 Answers2

0

To stop all child script, you could call .terminate(), .kill() methods:

import sys
import time
from subprocess import Popen

# start child processes
children = [Popen([sys.executable or 'python', scriptname])
            for scriptname in scripts_to_run]

time.sleep(30) # wait 30 seconds

for p in children:
    p.terminate() # or p.kill()

for p in children:
    p.wait() # wait until they exit
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • @user3265370: what solutions have you tried from [Best way to kill all child processes](http://stackoverflow.com/q/392022/4279)? – jfs Mar 25 '14 at 15:09
0

There are two approaches you can take.

The shell approach

If you only want to kill the child processes after the main app has finished but don't want the main app to handle this itself, for any reason (mostly its for debugging purposes), you can do it from the terminal:

   kill $(ps aux |grep -E 'python[[:space:]][[:alnum:]]+.py' |awk '{print $2}')  
             ▲     ▲                                      ▲            ▲  
             ║     ╚═══════════════════╦══════════════════╝            ║  
Get all ═════╝                         ║                               ║  
running                                ║                Get the second column  
processes                  Find all scripts executed         which is the PID 
                           by Python, ending with .py
                        (check Note 1 for more details)

Note 1: the regular expression in the upper example is just for demonstration purposes and it kills only scripts executed with a relative path like python script.py, but does not include processes like python /path/to/script.py. This is just an example, so make sure to adapt the regular expression to your specific needs.
Note 2: this approach is risky because it can kill unwanted applications, make sure you know what you are doing before using it.

The Python approach

The other approach offers more control, and is implemented in the main application itself. You can make sure that all child processes are exited when the main application ends by keeping track of all the processes you created, and killing them afterwards.

Example usage:
First change your process spawning code to keep the Popen objects of the running processes for later usage:

running_procs = []
for s in scripts_to_run:
    running_procs.append(
                  subprocess.Popen(["python", os.path.join(os.getcwd(), s)])
                        )

Then define the do_clean() function that will iterate through them and terminate them:

def do_clean():
    for p in running_procs:
        p.kill()

You can call this function manually whenever you wish to do this, or you can use the atexit module to do this when the application is terminating.

The atexit module defines a single function to register cleanup functions. Functions thus registered are automatically executed upon normal interpreter termination.

Note: The functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit() is called.

For example:

import atexit

atexit.register(do_clean)
bosnjak
  • 8,424
  • 2
  • 21
  • 47
  • don't say it is risky, just remove `kill` from `ps aux | ...` and provide example later `kill pid`, to avoid copy-paste accidents – jfs Mar 25 '14 at 15:14
  • note: [`atexit` handlers are called when the process exits "normally"](http://stackoverflow.com/q/22083422/4279) e.g., the handlers are not called if it is killed by SIGTERM signal – jfs Mar 25 '14 at 15:20
  • @J.F.Sebastian: i know the handlers are not killed by SIGTERM, that is not the point of the example, the point is to have a controlled killing process. – bosnjak Mar 25 '14 at 15:26
  • if the handlers are *not called* then they can't control anything – jfs Mar 25 '14 at 15:29
  • I'm not sure what you mean. The processes are running normally, and if the do_clean is called, they will be killed. Thats all there is about it. – bosnjak Mar 25 '14 at 15:33
  • `do_clean` is not called if the parent is killed by SIGTERM. Follow the link I've provided above – jfs Mar 25 '14 at 15:35
  • I know that, but that is not the case I am addressing here. Maybe I should've made it more clear.. I am only covering the case when the application is exited regularly. – bosnjak Mar 25 '14 at 15:37
  • There are tons of system scripts on Ubuntu that are Python scripts. Likely your regex does not contain `/` so it won't match neither system scripts nor the children created using `os.path.join(os.getcwd(), ..)` i.e., nothing gets killed – jfs Mar 25 '14 at 17:18
  • @J.F.Sebastian: i appreciate the notice, but I would think it is obvious that regular expressions need to be modified for everyones particular case, I am not trying to cover everything. Nevertheless, I have updated my answer to explain this in **Note 1**. Regards. – bosnjak Mar 25 '14 at 23:19