用python subprocess.Popen调用matlab函数

时间:2016-10-22 03:21:44

标签: python matlab python-2.7 subprocess popen

我有一个python代码,它在后台使用subprocess.Popen运行matlab函数sussum(a,nx,ny)。我无法让它发挥作用。因为我无法正确地将输入参数传递给matlab。这是python代码:

#!/usr/bin/env python
 import matlab.engine
 import scipy.io as sio
 import numpy as np
 import subprocess as sb
 nproc = 5
 input = sio.loadmat('sus_py.mat')
 totq = input['totq']
 nx,ny = input['nx'],input['ny']
 nq = totq+1
 nx,ny = matlab.int32(nx.tolist()) , matlab.int32(ny.tolist())
 iq = range(1,nq)
 gp = len(iq)/nproc
 list = [iq[j:j+nproc] for j in range(0,len(iq),nproc)]
 for g in range(0,len(list)):
     i = len(list[g])
     p = []
     for n in range(0,i):
         a = matlab.int32(list[g][n])
         fun = '-r "sussum(a,nx,ny); exit" '
         lmb = ['/usr/local/bin/matlab','-nodesktop','-nosplash','-nodisplay','-nojvm',fun]
         p.append(sb.Popen(lmb))
     for q in p:
         q.wait()

python脚本在集群网络的命令终端中执行,直到它发出错误消息:未定义的函数或变量'a'。

我确信matlab函数sussum(a,nx,ny)工作正常,因为我使用Python-Matlab API测试了它作为matlab.engine.start_matlab()。sussum(a,nx,ny)并给出了它期望的输出。任何有关使用subprocess.Popen()运行python代码的帮助都将受到高度赞赏。

1 个答案:

答案 0 :(得分:1)

当您使用subprocess.Popen(args)创建Popen对象时,您可以有效地使用它将lmb列表列表(使用空格连接)的内容传递给shell被执行。在这种情况下,您的命令的等价物将是:

/usr/local/bin/matlab -nodesktop -nosplah -nodisplay -nojvm -r "sussum(a,nx,ny); exit"

显然,如果直接从shell运行它会导致错误,因为此命令创建的MATLAB实例不知道anxny是变量,shell只是将整个事件视为在这种情况下作为参数传递给-r参数的字符串。如果从命令行运行此命令,则需要将这些符号替换为传递给MATLAB时具有某些意义的值。您可以通过在命令本身中手动编写变量,或者为您正在使用的shell使用适当的变量扩展方法来完成此操作。

如果您正在尝试通过Python Popen对象运行它,则需要将变量替换为实际的fun字符串。如果您在Python中使用严格,则可以执行类似

的操作
# define variables
a = 10
nx = [1, 2, 3, 4]
ny = [10, 20, 30, 40]

# build fun string from above variables
# -r "sussum(10, [1,2,3,4], [10,20,30,40]); exit;
fun = '-r "sussum({}, [{}], [{}]); exit";'.format(a, ','.join(nx), ','.join(ny))

不幸的是,既然您已经a nx提取了ny的{​​{1}},numpy.ndarrayscipy.io.loadmat值,那么在你面前有更多的工作要从那里提取值并将它们格式化为sussum函数可接受的格式。