FreeBixi
FreeBixi

Reputation: 139

Python: Ending an infinitely iterative subprocess

I have a python script that opens a .exe program using the subprocess module. This .exe program is an infinitely iterative script, in that it will continue to print the results of each iteration until the user closes the window. Every so often, it prints the results of the iteration into a file, replacing the previous data in the file.

My aims here are to:

  1. Run the .exe program, and test for the existence of the file it outputs.
  2. Once the file has been shown to exist, I need to run a test on the file to see if the iteration has converged to within a given tolerance. Once the iteration has converged, I need to kill the .exe subprocess.

This is my current code. It is designed to kill the subprocess once the iterate file has been created:

import subprocess
from subprocess import Popen, PIPE

fileexists = False

iteratecomms = Popen('iterate.exe', stdout=PIPE, stdin=PIPE, stderr=PIPE)

# Begin the iteration. Need to select options 1 and then 1 again at program menu
out, err = iteratecomms.communicate("1\n1\n".encode())

while (fileexists == False):
    fileexists = os.path.exists(filelocation)
else:
    Popen.kill(iteratecomms)

I know that this is incorrect; the issue is that as soon as I start the out, err = iteratecomms.communicate("1\n1\n".encode()) line, the program begins iterating, and does not move on to the next set of python code. Essentially, I need to start the .exe program, and at the same time test to see if the file has been created. I can't do this, however, because the program runs indefinitely.

How could I get around this? I have assumed that moving on to step 2 (testing the file and killing the subprocess under certain conditions) would not take too much work on top of this; if this is not true, how would I go about completing all of my aims?

Thank you very much for the help!

Edit: Clarified that the external file is overwritten.

Upvotes: 3

Views: 220

Answers (2)

Chris Barker
Chris Barker

Reputation: 2389

I would use the multiprocessing module.

pool = multiprocessing.Pool()
def start_iteration():
    return Popen('iterate.exe', stdout=PIPE, stdin=PIPE, stderr=PIPE)
pool.apply_async(start_iteration)
while (fileexists == False):
    fileexists = os.path.exists(filelocation)
Popen.kill(???)

The only problem now is that you'll have to somehow find the PID of the process without waiting for Popen to return (because Popen should never return.)

Upvotes: 1

Slater Victoroff
Slater Victoroff

Reputation: 21914

Assuming that you're trying to continuously trying to read this file I would suggest running a tail on the file in question. This can be done from a separate terminal in any *nix family OS, but otherwise I would check out this article for a Python implementation:

http://code.activestate.com/recipes/157035-tail-f-in-python/

After that if you want to kill the program running you should just be able to call terminate on the process running:

import subprocess
sub = subprocess.popen(#Whatever)

#Do something

sub.terminate()

Upvotes: 1

Related Questions