Python Mlab - 无法导入名称find_available_releases

KSS*_*KSS 8 python windows matlab matlab-deployment mlab python-mlab

我是Python的新手.我试图使用mlab包从Python内部运行MATLAB .我正在关注网站上的指南,我在Python命令行中输入了这个指南:

from mlab.releases import latest_release
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

cannot import name find_available_releases
Run Code Online (Sandbox Code Playgroud)

似乎matlabcom.py没有任何find_available_releases功能.

我可以知道是否有人知道如何解决这个问题?谢谢!

PS:我使用的是Windows 7,MATLAB 2012a和Python 2.7

Amr*_*mro 6

我浏览了代码,我认为所有README文件及其文档都不符合实际实现的内容.它似乎主要是从原始mlabwrap项目中复制而来.

这很令人困惑,因为mlabwrap使用C扩展模块实现与MATLAB Engine API的交互.但是mlab代码似乎已经用纯Python实现替换了那部分作为MATLAB桥接后端.它来自"Dana Pe'er Lab",它使用两种不同的方法与MATLAB交互,具体取决于平台(Windows 上的COM/ActiveX和Linux/Mac 上的管道).


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

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

但是你是在Windows上工作,并且代码并没有真正实现MATLAB版本之间选择这个平台的任何方式(因此所有的类似方法discover_locationfind_available_releases没用在Windows上).最后,COM对象创建为:

self.client = win32com.client.Dispatch('matlab.application')
Run Code Online (Sandbox Code Playgroud)

如此处所述,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)
Run Code Online (Sandbox Code Playgroud)

首先我添加了缺失的find_available_releases功能.我这样做是为了报告所有MATLAB版本都可用(就像我上面解释的那样,由于COM对象的创建方式,它并不重要).更好的解决方法是使用Windows注册表检测已安装/注册的MATLAB版本(检查密钥HKCR\Matlab.Application.X.Y并按照其中的CLSID HKCR\CLSID).这样您就可以真正选择并选择要运行的版本.

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

注意:在测试期间,每次调用脚本时都不能更快地启动/关闭MATLAB实例.这就是我self.eval('quit();')close函数中评论的原因.这样你可以使用(仅执行一次)启动MATLABmatlab.exe -automation,然后重复使用会话而不关闭它.完成后就杀了这个过程:)

这是一个测试模块的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()
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

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]
Run Code Online (Sandbox Code Playgroud)

matlab_peaks_surf matplotlib_peaks_surf


EDIT2:

以上变更已被接受并合并mlab.


Abh*_*rma 1

您说得对,没有编写 find_available_releases() 。有 2 种方法可以解决这个问题

  • 查看 Linux 中的代码并对其进行操作(您正在 Windows 上工作!)
  • 更改代码如下

在 matlabcom.py 中添加以下函数,如 matlabpipe.py 中所示

def find_available_releases():
    global _RELEASES
    if not _RELEASES:
        _RELEASES = list(_list_releases())
    return _RELEASES
Run Code Online (Sandbox Code Playgroud)

如果您看到 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
Run Code Online (Sandbox Code Playgroud)