user6039682
user6039682

Reputation:

Controlling a python script from another script

I am trying to learn how to write a script control.py, that runs another script test.py in a loop for a certain number of times, in each run, reads its output and halts it if some predefined output is printed (e.g. the text 'stop now'), and the loop continues its iteration (once test.py has finished, either on its own, or by force). So something along the lines:

for i in range(n):
    os.system('test.py someargument')
    if output == 'stop now': #stop the current test.py process and continue with next iteration
    #output here is supposed to contain what test.py prints

An attempt: test.py is this:

from itertools import permutations
import random as random


perms = [''.join(p) for p in permutations('stop')]

for i in range(1000000):
    rand_ind = random.randrange(0,len(perms))
    print perms[rand_ind]

And control.py is this: (following Marc's suggestion)

import subprocess

command = ["python", "test.py"]
n = 10
for i in range(n):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        output = p.stdout.readline().strip()
        print output
        #if output == '' and p.poll() is not None:
        #    break
        if output == 'stop':
            print 'sucess'
            p.kill()
            break
            #Do whatever you want
    #rc = p.poll() #Exit Code

Upvotes: 1

Views: 4730

Answers (4)

dodell
dodell

Reputation: 490

What you are hinting at in your comment to Marc Cabos' answer is Threading

There are several ways Python can use the functionality of other files. If the content of test.py can be encapsulated in a function or class, then you can import the relevant parts into your program, giving you greater access to the runnings of that code.

As described in other answers you can use the stdout of a script, running it in a subprocess. This could give you separate terminal outputs as you require.

However if you want to run the test.py concurrently and access variables as they are changed then you need to consider threading.

Upvotes: 1

Marc Cabos
Marc Cabos

Reputation: 39

You can use the "subprocess" library for that.

import subprocess

command = ["python", "test.py", "someargument"]

for i in range(n):
    p = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while True:
        output = p.stdout.readline()
        if output == '' and p.poll() is not None:
            break
        if output == 'stop now':
            #Do whatever you want
    rc = p.poll() #Exit Code

Upvotes: 0

6502
6502

Reputation: 114559

Yes you can use Python to control another program using stdin/stdout, but when using another process output often there is a problem of buffering, in other words the other process doesn't really output anything until it's done.

There are even cases in which the output is buffered or not depending on if the program is started from a terminal or not.

If you are the author of both programs then probably is better using another interprocess channel where the flushing is explicitly controlled by the code, like sockets.

Upvotes: 0

Marco smdm
Marco smdm

Reputation: 1045

You can use subprocess module or also the os.popen

os.popen(command[, mode[, bufsize]])

Open a pipe to or from command. The return value is an open file object connected to the pipe, which can be read or written depending on whether mode is 'r' (default) or 'w'.

With subprocess I would suggest

subprocess.call(['python.exe', command])

or the subprocess.Popen --> that is similar to os.popen (for instance)

With popen you can read the connected object/file and check whether "Stop now" is there.

The os.system is not deprecated and you can use as well (but you won't get a object from that), you can just check if return at the end of execution.

From subprocess.call you can run it in a new terminal or if you want to call multiple times ONLY the test.py --> than you can put your script in a def main() and run the main as much as you want till the "Stop now" is generated.

Hope this solve your query :-) otherwise comment again.

Looking at what you wrote above you can also redirect the output to a file directly from the OS call --> os.system(test.py *args >> /tmp/mickey.txt) then you can check at each round the file.

As said the popen is an object file that you can access.

Upvotes: 2

Related Questions