如何从Python捕获Matlab函数的输出
我正在运行下面的Python代码,它用来计算一个数组的平均值:
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])
从下面的Matlab脚本可以看到,输出结果返回给了y。我想从Python中获取这个输出。
function y = mean(x,dim)
...
...
end
这个解决方案必须适用于其他的Matlab函数。'mean'函数只是一个例子。
1 个回答
1
使用 fprintf
可以把需要的文本写入 stderr
。只需在开头加一个额外的参数 2
。
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]')
需要注意几点:
- 把 Python 的命令改成
subprocess.Popen
,这样可以处理stderr
的输出。 - 在 Matlab 的命令中,使用
fprintf
把想要的信息写入stderr
。这样可以把代码输出和 Matlab 的头部信息分开。 - 回到 Python 中,使用
Popen.communicate()
来获取stderr
的输出。 - 异常
ValueError
用来处理 Matlab 的退出事件(p
被关闭)。
编辑:
对于一个返回多个输出的函数
假设一个 Matlab 函数是
function [y, z] = foo(x)
y = x+1;
z = x*20;
end
关键是使用 fprintf
来输出结果,同时在 Matlab 中做其他事情时,和往常一样。
方法 1 - 内联脚本
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)
方法 2 - 独立脚本
首先创建一个新的 caller.m
脚本
[y, z] = foo(x);
for ii=1:length(y)
fprintf(2, '%d %d\n',y(ii),z(ii));
end
注意在从 Python 调用时要给 x
赋值;脚本共享同一个堆栈。(记得不要在调用脚本中 clear
工作区。)
然后,从 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)
把 Matlab 结果存储在 Python 变量中
当通过
stdout
/stderr
管道传递数据时:可以参考 这个 和
subprocess.check_output()
。当处理像
double
或二进制这样的复杂数据时:先用 Matlab 把数据写入一个外部文件。然后用 Python 读取这个文件。需要定义一个协议,让双方能够互相沟通。