0

I need to start a Python script in Python and keep it up.

For argument purposes, say that there is a program called slave.py

    if __name__=='__main__':
        done = False

        while not done:
            line = raw_input()
            print line
            if line.lower() == 'quit' or line.lower() == 'q':
                done = True
                break

            stringLen = len(line)
            print "len: %d " % stringLen

The program "slave.py" receives a string, calculates the input length of the string and outputs the length to stdout with a print statement.

It should run until I give it a "quit" or "q" as an input.

Meanwhile, in another program called "master.py", I will invoke "slave.py"

    # Master.py
    if __name__=='__main__':
        # Start a subprocess of "slave.py"
        slave = subprocess.Popen('python slave.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        x = "Hello world!"
        (stdout, stderr) = slave.communicate(x)

        # This works - returns 12
        print "stdout: ", stdout            

        x = "name is"
        # The code bombs here with a 'ValueError: I/O operation on closed file'
        (stdout, stderr) = slave.communicate(x)

        print "stdout: ", stdout

However, the slave.py program that I opened using Popen() only takes one communicate() call. It ends after that one communicate() call.

For this example, I would like to have slave.py keep running, as a server in a client-server model, until it receives a "quit" or "q" string via communicate. How would I do that with the subprocess.Popen() call?

SQA777
  • 352
  • 5
  • 15

2 Answers2

2

If each input line produces known number of output lines then you could:

import sys
from subprocess import Popen, PIPE

p = Popen([sys.executable, '-u', 'slave.py'], stdin=PIPE, stdout=PIPE)
def send(input):
    print >>p.stdin, input
    print p.stdout.readline(), # print input
    response = p.stdout.readline()
    if response:
        print response, # or just return it
    else: # EOF
        p.stdout.close()

send("hello world")
# ...
send("name is")
send("q")
p.stdin.close() # nothing more to send
print 'waiting'
p.wait()
print 'done'

Otherwise you might need threads to read the output asynchronously.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • No, I would need the program to stay up. THus, it looks like I need to either use threads or multiprocessing. – SQA777 Jul 13 '12 at 00:07
  • do you want 'slave.py' to stay alive when `master.py` exits? What happens if you start 2nd `master.py`? – jfs Jul 13 '12 at 01:49
0

If you indent to keep slave alive over the parent life-cycle you can daemonize it:

http://code.activestate.com/recipes/278731-creating-a-daemon-the-python-way/

Alternatively you could look multiprocess API:

http://docs.python.org/library/multiprocessing.html

... which allows thread-like processing over different child processes.

Mikko Ohtamaa
  • 82,057
  • 50
  • 264
  • 435