ArkanSaaS
ArkanSaaS

Reputation: 283

Subprocess, Popen Python

I want to run a program, let's say MATLAB or other FEA software from Python, wait for it to run and store results and later use again in Python to process further. I am not able to find a really basic example on how to do so. A simple code or any useful link will be highly appreciated. The help on Subprocess module seems a bit complicated.

Upvotes: 1

Views: 1206

Answers (1)

Takver
Takver

Reputation: 182

I just spent a while trying to work this out from frustratingly vague documentation and examples and finally got it figured out. Here's a really simple demo example:

How to run a MATLAB script from Python (using subprocess.Popen, without having to install the matlab engine)

Step 1: Create the MATLAB script you want to run. In this demo, I have two scripts, saved in the folder C:/Users/User/Documents/MATLABsubprocess :

triangle_area.m

b = 5;
h = 3;
a = 0.5*(b.* h);  
save('a.txt','a', '-ASCII')

triangle_area_fun.m

function [a] = triangle_area(b,h)
a = 0.5*(b.* h);   %area
save('a.txt','a', '-ASCII')
end

Step 2: Once these two .m files are created, the following Python script runs them using subprocess.Popen():

#Imports:
import subprocess as sp
import pandas as pd

#Set paths and options:
#note: paths need to have forward slashes not backslashes (why?!)
program  = 'C:/Program Files/MATLAB/R2017b/bin/matlab.exe'  #path to MATLAB exe
folder   = 'C:/Users/User/Documents/MATLABsubprocess'       #path to MATLAB folder with scripts to run
script   = 'triangle_area'                                  #name of script to run
options  = '-nosplash -nodesktop -wait'                     #optional: set run options  (nosplash? nodesktop means MATLAB won't open a new desktop window, wait means Python will wait until MATLAB is done beore continuing (needs to be paired with p.wait() after sp.Popen))
has_args = True                                             #set whether the MATLAB script needs arguments (i.e. is it a function?)

#Optional: define arguments to feed to function
if has_args ==True:
    script   = 'triangle_area_fun'                          #select script version with arguments
    b = 5 
    h = 3
    args = '({},{})'.format(b,h)                            #put all args into one string

#Set function string:
#Structure:  """path_to_exe optional_arguments -r "cd(fullfile('path_to_folder')), script_name, exit" """
#Example:    """C:/Program Files/MATLAB/R2017b/bin/matlab.exe -r "cd(fullfile('C:/Users/User/Documents/MATLABsubprocess')), triangle_area, exit" """
#basically, needs to know where the program to use lives, then takes some optional settings, -r runs the program, cd changes to the directory with the script, then needs the name of the script (possibly with arguments), then exits
fun =  """{} {} -r "cd(fullfile('{}')), {}, exit" """.format(program, options, folder, script)  #create function string that tells subprocess what to do
if has_args==True:
    fun = """{} {} -r "cd(fullfile('{}')), {}{}, exit" """.format(program, options, folder, script, args)
print('command:', fun)

#Run MATLAB:
print('running MATLAB script...')
p = sp.Popen(fun)                     #open the subprocess & run the MATLAB script 
p.wait()                              #wait until MATLAB is done before proceeding (this needs to be paired with -wait in options)
print('done')                         #if the run is successful, an output file named a.txt should appear in the folder with the MATLAB scripts

#Import MATLAB output files back into Python:
a = pd.read_csv('a.txt', header=None)             #read text file using pandas
print(a)

Upvotes: 1

Related Questions