Cómo capturar la salida de una función matlab de python

Estoy ejecutando el siguiente código de Python que evalúa la media de una matriz:

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]) 

Desde el script matlab a continuación, se puede ver el retorno de salida a y. Quiero capturar esta salida de python.

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

La solución debe ser aplicable a la otra función matlab. La función ‘media’ es solo un ejemplo.

Use fprintf para escribir el texto necesario en stderr . Solo agrega un argumento extra 2 al principio.

 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]') 

Algunas cosas a tener en cuenta:

  • Se cambió el comando de Python a subprocess.Popen , que permite la canalización stderr .
  • En el comando Matlab, use fprintf para escribir la información deseada en stderr . Esto puede separar la salida de código de las líneas de encabezado de Matlab.
  • De vuelta a Python, use Popen.communicate() para capturar la salida de stderr .
  • La excepción ValueError maneja el evento de salida de Matlab ( p está cerrado).

EDITAR:

Para una función que da múltiples salidas.

decir una función de Matlab es

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

El punto es usar fprintf para lanzar la salida, mientras haces todas las otras cosas como siempre haces en Matlab.

Método 1 – guión en línea

 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) 

Método 2 – secuencia de comandos independiente

Primero crea un nuevo script de caller.m

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

Tenga en cuenta que se debe asignar x al llamar desde Python; Los scripts comparten la misma stack. (Recuerde que NO debe clear el espacio de trabajo en la secuencia de comandos del llamante).

Entonces, llama al script desde 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) 

Almacenando el resultado de Matlab en una variable de Python

  • Al pasar datos a través de stdout / stderr pipe:

    Consulte esto y subprocess.check_output() .

  • Al manejar datos serios como double o binario:

    Escribe los datos en un archivo externo con Matlab. Luego lee este archivo con Python. Debe definirse un protocolo con el que ambos lados hablen entre sí.