teskata
teskata

Reputation: 11

How to run a command line program from Python

I have an atomic simulation program (written in Fortran, I don't have the source code) that prompts the user to input a temperature, mass of each atoms number of iterations, etc., and then runs a simulation of a given input file (specifying the initial positions of all the atoms). After all the iterations, the program outputs a text file with final positions of the atoms, and closes.

I'm trying to run identical simulations at different temperatures, so I wish to automate the input process through Python. Thus, the Python program will:

  1. Open the simulation program ('sim.exe')
  2. Input the temperature, mass, iterations, etc. into the command line automatically
  3. The output file will be generated and copied into another file of a different name so that it is not overwritten.
  4. Go back to number 1, at a different temperature, but the same mass, iterations, etc.

My main problem is number 2. I can't figure out how to input into the command line program from Python. Is it even possible? I've read that it would have something to do with the os or subprocess modules, but I'm not clear on how they work.

Note: I use Windows.

Upvotes: 1

Views: 2814

Answers (2)

Ulf Rompe
Ulf Rompe

Reputation: 929

If you can blindly input your data without waiting for specific prompts, the problem should be easy to solve:

import os
import shutil
import subprocess
import time

proc = subprocess.Popen(["sim.exe"], stdin=subprocess.PIPE)
while True:
    proc.communicate(input="line1\nline2\nline3\n")
    while not os.path.exists(outputfilepath):
        time.sleep(1)
    shutil.move(outputfilepath, uniq_outputfilepath)

Of course, it will be safer to scan the program's stdout and stderr for expected and unexpected patterns in order to proceed or abort. This would be possible by also setting the stdout and stderr args of Popen() to subprocess.PIPE and calling communicate like this:

stdout, stderr = proc.communicate(input="line1\nline2\nline3\n")

Check the communicate() documentation for details.

If you use Python3, the input string must be converted to a byte string to prevent communicate from raising "TypeError: 'str' does not support the buffer interface":

    proc.communicate(input=bytes("line1\nline2\nline3\n", "UTF-8"))

Upvotes: 7

John Riselvato
John Riselvato

Reputation: 12904

import sys
import subprocess

theproc = subprocess.Popen([sys.executable, "myCMDscript"])
theproc.communicate()

Upvotes: 4

Related Questions