Search code examples
pythonsubprocesspopen

Run a program from python several times whitout initialize different shells


I want to run a compiled Fortran numerical model from Python. It is too complex to compile it using F2PY without implement several changes in the Fortran routines. This is why I am just calling its executable using the subprocess module.

The problem is that I have to call it few thousands of times, and I have the feeling that generating soo many shells is slowing the whole thing.

My implememtation (It is difficult to provide a reproducible example, sorry) looks like:

import os
import subprocess

foo_path = '/path/to/compiled/program/'
program_dir = os.path.join(foo_path, "FOO")            #FOO is the Fortran executable
instruction = program_dir + " < nlst"                  #It is necesary to provide FOO a text file (nlst)
                                                       #with the configuration to the program

subprocess.call(instruction, shell=True, cwd=foo_path) #run the executable

Running it in this way (inside a loop), it works well and FOO generates a text file output that I can read from python. But I'd like to do the same keeping the shell active and just providing to it the "nlst" file path. Another nice option may be start an empty shell and keep it waiting for the instruction string, that will look like "./FOO < nlst". But I am not sure about how to do it, any ideas?

Thanks!

[Edited] Something like this should work but .comunicate ends process and a second call does not work:

from subprocess import Popen, PIPE

foo_path = '/path/to/FOO/'
process = Popen(['bash'], stdin=PIPE, cwd=foo_path)
process.communicate(b'./FOO < nlst')

Solution

  • I found this solution using the pexpect module,

    import pexpect
    import os.path
    
    foo_path = '/path/to/FOO/'
    out_path = '/path/to/FOO/foo_out_file'  #path to output file
    child = pexpect.spawn('bash', cwd=foo_path)
    child.sendline('./FOO < nlst')
    
    while not os.path.exists(out_path): #wait until out_path is created
        continue