Python Mlab – 无法导入名称find_available_releases

我是Python的新手。 我正在尝试使用mlab包从Python内部运行MATLAB。 我按照网站上的指南,我在Python命令行中input:

from mlab.releases import latest_release 

我得到的错误是:

 cannot import name find_available_releases 

似乎在matlabcom.py下没有find_available_releases函数。

请问有没有人知道如何解决这个问题? 谢谢!

PS:我正在使用Windows 7,MATLAB 2012a和Python 2.7

我浏览了代码,我不认为所有的README文件及其文档都与实际实现的相匹配。 它似乎主要是从原来的mlabwrap项目复制。

这是令人困惑的,因为mlabwrap是使用C扩展模块与MATLAB Engine API交互实现的。 然而, mlab代码似乎已经用一个纯粹的Python实现替代了这个部分作为mlab桥后端。 它来自“Dana Peer实验室” ,它使用两种不同的方法与MATLAB交互,具体取决于平台(Windows上的COM / ActiveX和Linux / Mac上的管道 )。


现在,我们了解后端的实现方式,您可以开始查看导入错误。

注意:代码中的Linux / Mac部分尝试在某些硬编码的固定位置查找 MATLAB可执行文件,并允许在不同版本之间进行选择。

然而,你正在使用Windows,代码并没有真正实现在这个平台的MATLAB版本之间进行选择的方式(所以像discover_locationfind_available_releases这样的所有方法在Windows上都是没用的)。 最后,COM对象被创建为 :

 self.client = win32com.client.Dispatch('matlab.application') 

正如这里所解释的 ,ProgID matlab.application不是版本特定的,只是简单地使用任何被注册为默认的MATLAB COM服务器。 我们可以明确指定我们想要的MATLAB版本(假设您有多个安装),例如matlab.application.8.3将选择MATLAB R2014a。

所以要修复代码,IMO最简单的方法就是摆脱所有关于多个MATLAB版本(在代码的Windows部分 )的逻辑,并且让它直接创建MATLAB COM对象。 我没有尝试过,但我不认为这太涉及了…祝你好运!


编辑:

我下载了模块,并设法让它在Windows上工作(我正在使用Python 2.7.6和MATLAB R2014a)。 这里是变化:

 $ git diff diff --git a/src/mlab/matlabcom.py b/src/mlab/matlabcom.py index 93f075c..da1c6fa 100644 --- a/src/mlab/matlabcom.py +++ b/src/mlab/matlabcom.py @@ -21,6 +21,11 @@ except: print 'win32com in missing, please install it' raise +def find_available_releases(): + # report we have all versions + return [('R%d%s' % (y,v), '') + for y in range(2006,2015) for v in ('a','b')] + def discover_location(matlab_release): pass @@ -62,7 +67,7 @@ class MatlabCom(object): """ self._check_open() try: - self.eval('quit();') + pass #self.eval('quit();') except: pass del self.client diff --git a/src/mlab/mlabraw.py b/src/mlab/mlabraw.py index 3471362..16e0e2b 100644 --- a/src/mlab/mlabraw.py +++ b/src/mlab/mlabraw.py @@ -42,6 +42,7 @@ def open(): if is_win: ret = MatlabConnection() ret.open() + return ret else: if settings.MATLAB_PATH != 'guess': matlab_path = settings.MATLAB_PATH + '/bin/matlab' diff --git a/src/mlab/releases.py b/src/mlab/releases.py index d792b12..9d6cf5d 100644 --- a/src/mlab/releases.py +++ b/src/mlab/releases.py @@ -88,7 +88,7 @@ class MatlabVersions(dict): # Make it a module sys.modules['mlab.releases.' + matlab_release] = instance sys.modules['matlab'] = instance - return MlabWrap() + return instance def pick_latest_release(self): return get_latest_release(self._available_releases) 

首先,我添加了缺少的find_available_releases函数。 我这样做是为了报告所有的MATLAB版本都可用(就像我之前解释过的那样,由于COM对象的创建方式,它并不重要)。 更好的解决办法是使用Windows注册表检测已安装/注册的MATLAB版本(检查HKCR\Matlab.Application.XY键,并在HKCR\CLSID按照它们的HKCR\CLSID )。 这样,你可以真正选择和选择运行的版本。

我还修复了两个不相关的错误(一个是作者忘记了函数返回值,另一个是不必要地创建了两次包装器对象)。

注意:在测试过程中,每次调用脚本时,不要启动/关闭一个MATLAB实例。 这就是为什么我在close函数中评论self.eval('quit();')的原因。 这样,你可以使用matlab.exe -automation 启动MATLAB (只做一次),然后反复重复使用会话而不关闭它。 只要你完成了就杀了这个过程:)

这里是一个测试模块的Python例子(我也展示了一个与NumPy / SciPy / Matplotlib的比较):

test_mlab.py

 # could be anything from: latest_release, R2014b, ..., R2006a # makes no difference :) from mlab.releases import R2014a as matlab # show MATLAB version print "MATLAB version: ", matlab.version() print matlab.matlabroot() # compute SVD of a NumPy array import numpy as np A = np.random.rand(5, 5) U, S, V = matlab.svd(A, nout=3) print "S = \n", matlab.diag(S) # compare MATLAB's SVD against Scipy's SVD U, S, V = np.linalg.svd(A) print S # 3d plot in MATLAB X, Y, Z = matlab.peaks(nout=3) matlab.figure(1) matlab.surf(X, Y, Z) matlab.title('Peaks') matlab.xlabel('X') matlab.ylabel('Y') matlab.zlabel('Z') # compare against matplotlib surface plot from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt fig = plt.figure() ax = fig.gca(projection='3d') ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='jet') ax.view_init(30.0, 232.5) plt.title('Peaks') plt.xlabel('X') plt.ylabel('Y') ax.set_zlabel('Z') plt.show() 

这是我得到的输出:

 C:\>python test_mlab.py MATLAB version: 8.3.0.532 (R2014a) C:\Program Files\MATLAB\R2014a S = [[ 2.41632007] [ 0.78527851] [ 0.44582117] [ 0.29086795] [ 0.00552422]] [ 2.41632007 0.78527851 0.44582117 0.29086795 0.00552422] 

matlab_peaks_surfmatplotlib_peaks_surf


EDIT2:

上述变更已被接受并合并到mlab

你说的没有写find_available_releases()是正确的。 2种方法来解决这个问题

  • 检查在Linux中的代码,并在其上工作(您正在使用Windows!)
  • 更改代码如下

在matlabp.py中添加以下函数

 def find_available_releases(): global _RELEASES if not _RELEASES: _RELEASES = list(_list_releases()) return _RELEASES 

如果你看到mlabraw.py文件,下面的代码会给你一个清晰的概念,为什么我这么说!

 import sys is_win = 'win' in sys.platform if is_win: from matlabcom import MatlabCom as MatlabConnection from matlabcom import MatlabError as error from matlabcom import discover_location, find_available_releases from matlabcom import WindowsMatlabReleaseNotFound as MatlabReleaseNotFound else: from matlabpipe import MatlabPipe as MatlabConnection from matlabpipe import MatlabError as error from matlabpipe import discover_location, find_available_releases from matlabpipe import UnixMatlabReleaseNotFound as MatlabReleaseNotFound