win10环境下在python3中需要调用matlab脚本可以有3种方式:
1、使用transplant库
transplant(可以选择通过SSH)运行时会打开一个Matlab子进程,并通过地ØMQ以请求-响应模式连接到它。然后Matlab远程运行transplant,开始监听消息。此后,Python可以向Matlab发送消息,Matlab会响应。从Python到Matlab的发送/接收和编码/解码值的往返时间约为2毫秒。
transplant库的详细信息可以参考其github。
安装方法:
1、Install the zeromq library on your computer and add it to your PATH. Alternatively, Transplant automatically uses conda's zeromq if you use conda.
2、Install Transplant using pip install transplant. This will install pyzmq, numpy and msgpack as dependencies.
需要注意的是在windows中安装transplant时需要本机上有matlab支持的编译器,不同版本的matlab支持的编译器也不同,在安装好matlab之后再安装符合要求的编译器(我安装的是visual studio 2013,对应matlab版本为r2015b),再使用pip安装pyzmq,之后可能需要重启才能使用。
同时环境变量里需要将zmq.h
的路径添加上,matlab也必须能够在cmd里启动,如果不能就将matlab路径添加到环境变量。
使用方法:
import transplant
matlab = transplant.Matlab()
# 调用matlab函数,
length = matlab.numel([1, 2, 3])
magic = matlab.magic(2)
spectrum = matlab.fft(numpy.random.randn(100))
# 调用自己的matlab函数
a=10
b=3
test = matlab.myfunc(a/1,b/1)
在使用transplant时需要注意的是有可能会报Undefined function 'fft' for input arguments of type 'int8'. (MATLAB:UndefinedFunction)
这样的错,这是因为我们在python中传给matlab的参数是整数,我们需要把参数转换为浮点数,将参数/1
是一种方便的转为浮点数的方法。
2、使用MATLAB Engine API for Python
在使用该方法之前先去https://www.mathworks.com/help/releases/R2017b/matlab/matlab_external/system-requirements-for-matlab-engine-for-python.html
查询不同matlab版本支持的python版本(查询方法是将网址中的matlab版本号R2017b替换为你想查询的即可)。比如R2015b最高支持到python3.4,那么如果想用tensorflow 2.0(最低支持python 3.5)就只能使用matlab R2016b版本。ps:我就被坑过…
安装方法:
当电脑上安装了多个版本的matlab时确保当前想使用的matlab是默认matlab,在cmd界面输入matlab之后运行的matlab版本就是系统当前默认matlab。
在matlab中使用matlabroot
查询当前matlab的根目录,之后将下面命令的matlabroot
替换为查询到的路径:
cd "matlabroot\extern\engines\python"
python setup.py install
使用方法:
import matlab.engine
# start
eng = matlab.engine.start_matlab()
# matlab无法直接使用python数组,需要使用double方法转换
a = matlab.double([1,4,9,16,25])
# 调用matlab自带函数
b = eng.sqrt(a)
print(b)
# 调用用户自己的函数
c=eng.myfunc(a,b)
# stop
eng.quit()
更加详细的使用方法可以参考matlab文档
3、使用oct2py库
oct2py是一个使python能调用octave的库,因为octave能够兼容大部分matlab函数,因此这也是一种在python中使用matlab脚本的方法。oct2py的详细资料可以参考github。
安装方法:
oct2py需要调用octave,所以电脑上需要安装octave。
之后使用pip install oct2py
或conda install -c conda-forge oct2py
进行安装。
使用方法:
from oct2py import octave
import numpy as np
a=np.random.randn(16000,1)
# 调用matlab自带函数
b = octave.sqrt(a)
print(b)
# 调用用户自己的函数
c=octave.myfunc(a,b)
4、性能比较
方法1、2和matlab直接运行的运行时间可以参考Calling Matlab from Python,结论是matlab直接运行比方法1快100倍左右,比方法2快1000倍左右。
因为我的matlab engine不兼容python 3.6,所以没有做方法2的运行时间测试。下面是方法1、3和使用python原生方法多次运行同一操作的时间对比:
方法1:transplant运行时间
程序运行时间:3.644000 s
程序运行时间:4.001000 s
程序运行时间:3.441067 s
程序运行时间:3.628064 s
程序运行时间:3.476122 s
程序运行时间:3.290023 s
程序运行时间:3.734999 s
程序运行时间:3.876015 s
程序运行时间:3.296023 s
方法3:oct2py运行结果
程序运行时间:25.69352 s
程序运行时间:25.62646 s
程序运行时间:25.52894 s
程序运行时间:24.94850 s
程序运行时间:25.18549 s
python原生实现运行时间
程序运行时间:1.321417 s
程序运行时间:1.372258 s
程序运行时间:1.410514 s
程序运行时间:1.570063 s
程序运行时间:1.349001 s
程序运行时间:1.309512 s
程序运行时间:1.273514 s
程序运行时间:1.408056 s
程序运行时间:1.276262 s
程序运行时间:1.471999 s
从结果可以看到,除了python原生之外,transplant的速度比oct2py要快很多。
因此,如果想要在python中调用matlab脚本,比较推荐的方法是使用transplant。但是这仅限于我测试的这一脚本,是否具有普适性还不确定。