beemurt
Posts: 16
Joined: Fri May 24, 2019 4:27 pm

Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 5:16 pm

Good Afternoon

Hopefully someone can help me. I am new-ish to python/programming.

I have a script which controls when another script gets called for an alarm system.

Basically i want to call tryingToSpawn.py if two vars in a database are set. If two different vars are set I want to kill/terminate tryingToSpawn.py. But I am having problems getting it to work.

The first subprocess is to establish if a phone is present on the LAN. This works perfectly! It is the second subprocess seems to work too. Its just when I try to stop it, it fails. The code and error is below

This is the code:

Code: Select all

import subprocess
from subprocess import Popen, PIPE
import signal
import sys
import os

try:
# while loop checks status before the if statements are checked
    while True:
        # pull data from DB - SQL
        for row in records:
           #list of vars
# determine the location of the a mobile 
            result = subprocess.check_output("sudo nmap -sn 192.168.0.0-50", shell = True)
            if (mac in result):
                deviceLocation = 1
            elif (mac not in result):
                deviceLocation = 2
            # if statements control the actions of the script
            if (routineStatus == 1) and (deviceTriggerLocation == deviceLocation):
                if componentsid == 5 and routineAction == 1:
                   proc1 = subprocess.Popen( "exec" 'python tryingToSpawn.py', shell=True)
                if componentsid == 5 and routineAction == 2:
                    os.kill(proc1.pid, signal.SIGINT)
            if routineStatus == 0:
                os.kill(proc1.pid, signal.SIGINT)
                mySQLconnection.close()
                sys.exit()

# encase DB fails - trace error
except Error as e:
    print("Error while connecting to oh_Database-:", e)

# closing resources
finally:
    if(mySQLconnection.is_connected()):
        mySQLconnection.close()


I am just trying to run this from terminal. This is the error i get:
Traceback (most recent call last):
File "routineDevice.py", line 156, in <module>
os.kill(proc1.pid, signal.SIGINT)
NameError: name 'proc1' is not defined

I think I do understand that for some reason 'proc1' is out of scope as a var, inside the other if statements. Can anyone help, suggest a different way of doing this? I just need to have the parent script launch a child python script (the child needs to run in the background without hanging up the parent script) and then the parent needs to be able to stop the child using a few if statements.

Is this possible?

Many Thanks
B

User avatar
MrYsLab
Posts: 351
Joined: Mon Dec 15, 2014 7:14 pm
Location: Noo Joysey, USA

Re: Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 5:47 pm

It is a little difficult to understand what the coding is actually doing, but I modified it so that proc1 is initialized to None at the top of the loop and to throw an exception if proc1 is None when a kill is called. This should at least point out where the issue is and you can correct from there:

Code: Select all

import subprocess
from subprocess import Popen, PIPE
import signal
import sys
import os

try:
    # while loop checks status before the if statements are checked
    while True:
        
        # initialize proc1 to None
        proc1 = None
        # pull data from DB - SQL
        for row in records:
            # list of vars
            # determine the location of the a mobile
            result = subprocess.check_output("sudo nmap -sn 192.168.0.0-50", shell=True)
            if mac in result:
                deviceLocation = 1
            elif mac not in result:
                deviceLocation = 2
            # if statements control the actions of the script
            if (routineStatus == 1) and (deviceTriggerLocation == deviceLocation):
                if componentsid == 5 and routineAction == 1:
                    proc1 = subprocess.Popen("exec" 'python tryingToSpawn.py', shell=True)
                if componentsid == 5 and routineAction == 2:
                    if proc1:
                        os.kill(proc1.pid, signal.SIGINT)
                    else:
                        raise RuntimeError('Proc 1 is None: 1')
            if routineStatus == 0:
                if proc1:
                    os.kill(proc1.pid, signal.SIGINT)
                else:
                    raise RuntimeError('Proc 1 is None: 2')
                mySQLconnection.close()
                sys.exit()

# encase DB fails - trace error
except Error as e:
    print("Error while connecting to oh_Database-:", e)

# closing resources
finally:
    if mySQLconnection.is_connected():
        mySQLconnection.close()

beemurt
Posts: 16
Joined: Fri May 24, 2019 4:27 pm

Re: Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 6:11 pm

Thank you for the reply MrYsLab

I implemented the code you provided and got this response in terminal:

Traceback (most recent call last):
File "routineDevice.py", line 160, in <module>
raise RuntimeError('Proc 1 is None: 1')
RuntimeError: Proc 1 is None: 1

The DB is set so that it will hit - if componentsid == 5 and routineAction == 2:

So it appears it is still failing this section below:

Code: Select all

if componentsid == 5 and routineAction == 2:
                    if proc1:
                        os.kill(proc1.pid, signal.SIGINT)
                    else:
                        raise RuntimeError('Proc 1 is None: 1')

User avatar
MrYsLab
Posts: 351
Joined: Mon Dec 15, 2014 7:14 pm
Location: Noo Joysey, USA

Re: Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 6:26 pm

Again, I am not really sure what the code is supposed to do, but a possible solution is to replace the raise statements with continue to go to the next iteration of the loop:

Code: Select all

            if (routineStatus == 1) and (deviceTriggerLocation == deviceLocation):
                if componentsid == 5 and routineAction == 1:
                    proc1 = subprocess.Popen("exec" 'python tryingToSpawn.py', shell=True)
                if componentsid == 5 and routineAction == 2:
                    if proc1:
                        os.kill(proc1.pid, signal.SIGINT)
                    else:
                        continue
            if routineStatus == 0:
                if proc1:
                    os.kill(proc1.pid, signal.SIGINT)
                    mySQLconnection.close()
                    sys.exit()
                else:
                    continue

beemurt
Posts: 16
Joined: Fri May 24, 2019 4:27 pm

Re: Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 6:54 pm

Unfortunately the continue statements just let the code run in a loop, they dont kill the child script.

The code is part of an alarm system. This is the sudo code for what i am trying to do:

Check if a device is on the LAN. If it is enter some if statements:
if componentsid == 5 and routineAction == 1:
run the alarm.py script which waits for a PIR event.
Once PIR tripped alarm.py takes image with camera and sends a whatsapp message.
It stays live until the PIR event has been triggered
if componentsid == 5 and routineAction == 2:
the alarm is to be disabled, if running (as a child) exit before a PIR event.

I hope that makes sense?

User avatar
Paeryn
Posts: 2609
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 8:08 pm

In your original code, when you were getting the NameError: proc1 not defined, that was happening because at the point in time when the os.kill was trying to be executed, the preceding event which spawns it (and creates the proc1 variable) obviously hasn't happened, otherwise proc1 would have had a value.

You look to have an error when trying to spawn the subprocess

Code: Select all

proc1 = subprocess.Popen("exec" 'python tryingToSpawn.py', shell=True)
The string you are passing is the concatenation of the two strings, i.e. effectively

Code: Select all

proc1 = subprocess.Popen('execpython tryingToSpawn.py', shell=True)
and I doubt there is a program called execpython, so the Popen() will not do anything.

Also, rather than using os.kill() to send a signal you should just send it with

Code: Select all

proc1.send_signal(SIGINT)
And you should ideally call

Code: Select all

proc1.wait()
afterwards to get the subprocess' return code and let the Kernel know that you have finished with it (although IIRC Python will put a Popen object into a private list when it goes out of scope and will automatically wait() on any in that list which have teminated if you don't do it yourself).
Last edited by Paeryn on Sat Jul 13, 2019 8:48 pm, edited 1 time in total.
She who travels light — forgot something.

beemurt
Posts: 16
Joined: Fri May 24, 2019 4:27 pm

Re: Subprocessing? Calling and terminating a python script from another python script

Sat Jul 13, 2019 8:43 pm

Evening Paeryn

Your correct, the subrprocess was wrong it should read:

Code: Select all

process = subprocess.Popen('python alarmTest.py', shell=True)
And I think you are right my code inst logically correct either. I will take a look and see if i can fix it up

Thank you

Return to “Python”