How to catch output of a matlab function from pyth

2019-05-14 03:03发布

I'm running the python code below which evaluates mean of an array:

def matlab_func1(array):
    p = os.popen('matlab -nodesktop -nosplash  -r "mean('+str(array)+');exit"')
    while 1:
        line = p.readline()
        if not line:
            break
        print line

matlab_func1([1,2,3]) 

From the matlab script below, it can be seen output return to y. I want to catch this output from python.

function y = mean(x,dim)
...
...
end

The solution must be applicable to the other matlab function. The 'mean' function is just an example.

1条回答
迷人小祖宗
2楼-- · 2019-05-14 03:34

Use fprintf to write needed text into stderr. Just add an extra argument 2 in the beginning.

import subprocess
import os
def matlab_func1(array):
    p = subprocess.Popen(['/home/user/Matlab/bin/matlab', '-nodesktop', '-nosplash', '-r "m = mean(' + str(array) + ');fprintf(2, \'%d\\n\',m);exit" >/dev/null'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while 1:
        try:
            out, err = p.communicate()
        except ValueError:
            break
        print 'hello' + err

matlab_func1('[1,2,3]') 

A few things to note:

  • Changed the Python command to subprocess.Popen, which allows stderr piping.
  • In Matlab command, use fprintf to write wanted info into stderr. This can separate code ouput from Matlab's header lines.
  • Back into Python, use Popen.communicate() to catch stderr output.
  • The exception ValueError handles exit event of Matlab (p is closed).

EDIT:

for a function that gives multiple outputs

say a Matlab function is

function [y, z] = foo(x)
    y = x+1;
    z = x*20;
end

The point is use fprintf to throw the output, while doing all other things as you always do normally in Matlab.

Method 1 - in-line script

p = subprocess.Popen(['/home/user/Matlab/bin/matlab', '-nodesktop', '-nosplash', '-r "[y, z] = foo(' + str(array) + ');for ii=1:length(y) fprintf(2, \'%d %d\\n\',y(ii),z(ii)); end; exit" >/dev/null'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Method 2 - standalone script

First create a new caller.m script

[y, z] = foo(x);
for ii=1:length(y)
    fprintf(2, '%d %d\n',y(ii),z(ii));
end

Note that x is to be assigned when calling from Python; scripts share the same stack. (Remember NOT to clear the workspace in the caller script. )

Then, call the script from Python

p = subprocess.Popen(['/home/user/Matlab/bin/matlab', '-nodesktop', '-nosplash', '-r "x=' + str(array) + ';caller; exit" >/dev/null'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Storing Matlab result in a Python variable

  • When passing data through stdout / stderr pipe:

    Refer to this and subprocess.check_output().

  • When handling serious data like double or binary:

    Write the data into an external file with Matlab. Then read this file with Python. A protocol with which both side talk with each other should be defined.

查看更多
登录 后发表回答