Oliver
Oliver

Reputation: 119

How to kill subprocesses with another command python

I am running two subprocesses in a Python server script. The purpose of the subprocesses is to stream video from my Raspberry Pi.

My question is how to kill the subprocesses when another command is sent to the server. I am currently using Popen() to start the subprocesses.

This is my code for when the server receives the command "startStream". I am using Twisted library as server protocol.

class Echo(Protocol):
   def connectionMade(self):
        #self.transport.write("""connected""")
        self.factory.clients.append(self)
        print "clients are ", self.factory.clients

    def connectionLost(self, reason):
        self.factory.clients.remove(self)

    def dataReceived(self, data):
        print "data is ", data

        if data == "startStream":
            p = subprocess.Popen("raspistill --nopreview -w 640 -h 480 -q 5 -o /tmp/stream/pic.jpg -tl 100 -t 9999999 -th 0:0:0 &", shell=True)
            pn = subprocess.Popen("LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i %s -o %s &" % (x,y), shell=True)

What I would like is something like this.

if data == "startStream":
        p = subprocess.Popen("raspistill --nopreview -w 640 -h 480 -q 5 -o /tmp/stream/pic.jpg -tl 100 -t 9999999 -th 0:0:0 &", shell=True)
        pn = subprocess.Popen("LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i %s -o %s &" % (x,y), shell=True)
elif data == "stopStream":
        os.kill(p.pid)
        os.kill(pn.pid)

Many thanks!

Upvotes: 0

Views: 248

Answers (1)

Łukasz Rogalski
Łukasz Rogalski

Reputation: 23213

You're missing some context here, but basically server would do something like:

while True:
    data = wait_for_request()
    if data == 'startStream':
        p = subprocess.Popen("raspistill --nopreview -w 640 -h 480 -q 5 -o /tmp/stream/pic.jpg -tl 100 -t 9999999 -th 0:0:0 &", shell=True)
        pn = subprocess.Popen("LD_LIBRARY_PATH=/usr/local/lib mjpg_streamer -i %s -o %s &" % (x,y), shell=True)
    elif data == 'stopStream':
        p.terminate()
        pn.terminate()

The crucial part is that names p and pn exists in same scope and therefore they are accessible without using any kind of global state. If your code structure is different, you need to outline it in question.

Since data_received has it's own scope on each call, you need to pass a reference to your Popen object in different way. Fortunately, you may keep references in the class instance.

def dataReceived(self, data):
    if data=='startStream':
        self.p = subprocess.Popen()  # ...
        self.pn = subprocess.Popen()  # ...
    elif data=='stopStream':
        self.p.terminate()
        self.pn.terminate()

Popen.terminate is available from Python 2.6 and should work just fine - I'm not sure what's an issue in question's comments.

Upvotes: 1

Related Questions