I have a python script that is constantly listening out for a json message from another server. When it receives a message one of the values is placed into a variable. Once this message is received I need another python script to be launched and the variable past over to it to be processed. Can anyone help me with how to do this?

I'm very new to python and would really appreciate any help you can give me, as I'm struggling to understand some of the other answers to similar questions.

Thank you!

Below is the code constantly running to receive messages:

class MyListener(stomp.ConnectionListener):
    def on_error(self, headers, message):
        print 'received an error %s' % message

    def on_message(self, headers, message):
        print 'received a message %s' % message
        obj = json.loads(message)
        detectedimsi = obj["imsi"]
        print detectedimsi
share|improve this question

To run any other program, you just use the functions in the subprocess module. But there are three complexities.

First, you want to run another Python script, not a binary. Presumably you want to run it with the same version of Python that you're running in, even if there are multiple Pythons installed. So, you want to use sys.executable as the program. For example:

subprocess.check_call([sys.executable, 'otherscript.py'])

Second, you want to pass some data. For small amounts of printable string data that will fit on the command line, just pass them as an argument:

subprocess.check_call([sys.executable, 'otherscript.py', detectedimsi])

Then, in the other script, you just look at sys.argv[1] to receive the data.

If you're trying to pass binary data, or a large amount of text, you will want to pass it over a pipe. The simplest way to do that is to pass it via stdin. But I don't think that's relevant here.

Third, you're trying to do this inside an asynchronous network client or server. So, you can't just run another script and block until it's finished, unless you're absolutely sure that it's going to finish very fast. If your server framework has a way to integrate subprocesses into it (Twisted is the only one I've ever used that does, but there may be others), great. You can fake it if you can toss the process's stdout pipe into your framework's event loop (basically, if you don't care about Windows, and your framework has a way to add a file to the reactor). But otherwise, you will have to use a thread.

I'm assuming you don't need to get any results from the other script, or even know when it's done. If that's not true, it gets a bit more complicated.

Putting it all together:

def on_message(self, headers, message):
    print 'received a message %s' % message
    obj = json.loads(message)
    detectedimsi = obj["imsi"]
    print detectedimsi
    thread = threading.Thread(target=subprocess.call, 
                              args=[[sys.executable, 'otherscript.py', detectedimsi]])
    thread.daemon = True
    thread.start()
share|improve this answer

You'll need the subprocess module:

import subprocess

Then in your on_message() method, you can start the other process:

  def on_message(self, headers, message):
    …
    outputOfOtherProcess = subprocess.check_output([
      '/path/to/other/process',
      json.dumps(detectedimsi) ])

Your other process will receive the value you want to pass as sys.argv[1] in JSON format (so it will need to use json.loads(sys.argv[1])).

Other ways of passing the value are possible, but passing it as command line argument might be sufficient for your case (depends on the data's size and other things).

As abarnert pointed out, some things should be mentioned:

  • This way of calling a subprocess will block until the subprocess is finished. This might be a problem in case your script is supposed to be reactive again before the subprocess is finished.
  • Calling the subprocess script by giving its path as executable might fail on systems which do not provide the direct calling of scripts. In these cases you will have to call the interpreter (which can be accessed as sys.executable) and pass the path to the script as first parameter instead (and the remaining parameters after that).
share|improve this answer
    
That's going to block his on_message handler until the other process finishes, which is usually a very bad idea in a network app. – abarnert May 28 '13 at 9:38
    
Also, you can't just run a Python script as a program like this. You need to run the Python interpreter, and pass the script as the first argument. – abarnert May 28 '13 at 9:38
    
He only said that he got the value from a server, not that he was writing a server. Running scripts: There might be OSes on which you are right. On Linuxes such Python scripts typically get their magic hashbang-line (#!/usr/bin/env python or similar) and execute permissions, then they can be executed as standalone-programs just fine. – Alfe May 28 '13 at 9:41
    
The shell will check a shebang line, but the OS usually won't, and you're not running with shell=True. Linux's binfmt module is a special case, but it depends on how it's configured; on many linux systems you still can't do this (usually intentionally configured that way for security reasons). And on just about any other POSIX system, it's not possible at all. – abarnert May 28 '13 at 10:09
    
Well, all system's I've been on yet it works just fine. But thank you for pointing out that there might be sth to be done additionally in case that does not work out of the box. – Alfe May 28 '13 at 10:10

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.