【问题标题】:Call Python function from MATLAB从 MATLAB 调用 Python 函数
【发布时间】:2010-12-15 00:48:06
【问题描述】:

我需要从 MATLAB 调用 Python 函数。我该怎么做?

【问题讨论】:

标签: python matlab language-interoperability


【解决方案1】:

您可以先embed your Python script in a C program,然后再MEX the C program with MATLAB,但与将结果转储到文件相比,这可能需要大量工作。

您可以使用PyMat 在 Python 中调用 MATLAB 函数。除此之外,SciPy 有几个 MATLAB 重复函数。

但如果您需要从 MATLAB 运行 Python 脚本,您可以尝试运行 system 命令来运行脚本并将结果存储在一个文件中,稍后在 MATLAB 中读取它。

【讨论】:

    【解决方案2】:

    我对我的系统有类似的要求,这是我的解决方案:

    在 MATLAB 中有一个名为 perl.m 的函数,它允许您从 MATLAB 调用 perl 脚本。根据您使用的版本,它将位于类似的位置

    C:\Program Files\MATLAB\R2008a\toolbox\matlab\general\perl.m
    

    创建一个名为 python.m 的副本,用 python 快速搜索和替换 perl,仔细检查它设置的命令路径以指向你的 python 安装。您现在应该可以从 MATLAB 运行 python 脚本了。

    示例

    python 中保存为“sqd.py”的简单平方函数,如果我正确执行此操作,我自然会在测试输入参数、有效数字等方面进行一些检查。

    import sys
    
    def squared(x):
        y = x * x
        return y
    
    if __name__ == '__main__':
        x = float(sys.argv[1])
        sys.stdout.write(str(squared(x)))
    

    然后在 MATLAB 中

    >> r=python('sqd.py','3.5')
    r =
    12.25
    >> r=python('sqd.py','5')
    r =
    25.0
    >>
    

    【讨论】:

    • perl 只是进行系统调用来执行 Perl 脚本 - Perl 脚本和 MATLAB 之间没有数据传输,除了“尝试 Perl 调用 result 的结果及其退出状态状态。” - mathworks.com/access/helpdesk/help/techdoc/ref/perl.html
    • 我同意它只是进行系统调用,但是如果不需要,为什么要使用 mex 函数和套接字使事情变得复杂呢?在简单的层面上,对 python 的调用确实有一个简单的数据传输。我会用一个例子来更新答案。
    • +1 - MATLAB 示例代码看起来很棒 - 你能发布(代码/链接)python.m 吗?返回的数据有什么限制 - 仅限标量?
    • 我们可以将数组作为参数传递给python文件吗?
    • 请注意,这可行,但它是一个 hack,有很多路径并没有真正去任何地方,例如,fullfile(matlabroot, 'sys\python\win32\bin\'); 指向的路径实际上并不存在,没有定义了任何 python 错误消息,因此message('MATLAB:python:<>') 错误消息在 CTRL+F'd Perl.m 中不起作用
    【解决方案3】:

    由于Python 是一种更好的粘合语言,因此从Python 调用程序的MATLAB 部分可能更容易,反之亦然。

    查看Mlabwrap

    【讨论】:

      【解决方案4】:

      由于MATLAB 与 Java 无缝集成,您可以使用Jython 编写脚本并从 MATLAB 调用它(您可能需要添加一个纯 JKava 瘦包装器才能真正调用 Jython 代码)。我从未尝试过,但我不明白为什么它不起作用。

      【讨论】:

        【解决方案5】:

        我已将 perl.m 调整为 python.m 并将其附上以供其他人参考,但我似乎无法从 Python 脚本中获得任何输出以返回到 MATLAB 变量:(

        这是我的 M 文件;请注意,我在代码中直接指向 Python 文件夹 C:\python27_64,这会在您的系统上发生变化。

        function [result status] = python(varargin)
        cmdString = '';
        for i = 1:nargin
            thisArg = varargin{i};
            if isempty(thisArg) || ~ischar(thisArg)
                error('MATLAB:python:InputsMustBeStrings', 'All input arguments must be valid strings.');
            end
            if i==1
                if exist(thisArg, 'file')==2
                    if isempty(dir(thisArg))
                        thisArg = which(thisArg);
                    end
                else
                    error('MATLAB:python:FileNotFound', 'Unable to find Python file: %s', thisArg);
                end
            end
          if any(thisArg == ' ')
            thisArg = ['"', thisArg, '"'];
          end
          cmdString = [cmdString, ' ', thisArg];
        end
        errTxtNoPython = 'Unable to find Python executable.';
        if isempty(cmdString)
          error('MATLAB:python:NoPythonCommand', 'No python command specified');
        elseif ispc
          pythonCmd = 'C:\python27_64';
          cmdString = ['python' cmdString];  
          pythonCmd = ['set PATH=',pythonCmd, ';%PATH%&' cmdString];
          [status, result] = dos(pythonCmd)
        else
          [status ignore] = unix('which python'); %#ok
          if (status == 0)
            cmdString = ['python', cmdString];
            [status, result] = unix(cmdString);
          else
            error('MATLAB:python:NoExecutable', errTxtNoPython);
          end
        end
        if nargout < 2 && status~=0
          error('MATLAB:python:ExecutionError', ...
                'System error: %sCommand executed: %s', result, cmdString);
        end
        

        编辑:

        解决了我的问题,原来的 perl.m 通过更新 PATH 然后调用 Perl 指向 MATLAB 文件夹中的 Perl 安装。上面的函数指向我的 Python 安装。当我调用我的function.py 文件时,它位于不同的目录中并调用了该目录中的其他文件。这些没有反映在 PATH 中,我不得不将我的 Python 文件轻松安装到我的 Python 发行版中。

        【讨论】:

          【解决方案6】:

          最简单的方法是使用MATLABsystem 函数。

          所以基本上,您可以在 MATLAB 上执行 Python 函数,就像在命令提示符 (Windows) 或 shell (Linux) 上一样:

          system('python pythonfile.py')
          

          以上内容仅用于运行 Python 文件。如果你想运行一个 Python 函数(并给它一些参数),那么你需要这样的东西:

          system('python pythonfile.py argument')
          

          举个具体的例子,把 Adrian 对这个问题的回答中的 Python 代码保存到一个 Python 文件中,即test.py。然后将此文件放在您的 MATLAB 目录中并在 MATLAB 上运行以下命令:

          system('python test.py 2')
          

          您将得到 4 或 2^2 作为输出。

          注意:MATLAB 在当前 MATLAB 目录中查找您使用 system 命令指定的任何 Python 文件。

          这可能是解决您的问题的最简单方法,因为您只需使用 MATLAB 中的现有函数进行投标。

          【讨论】:

          • 这就是我一直在做的事情,但我遇到了一个神秘的问题——我的 python 脚本的一个参数是一个文件。从 MATLAB 调用时,python 脚本找不到该文件(尽管所有脚本都与该文件位于同一目录中,并且尽管在 MATLAB 脚本中指定了完整路径)。令人抓狂。
          • 建议看起来不错,但我收到错误消息“'python' 不是内部或外部命令、可运行程序或批处理文件。”
          【解决方案7】:

          这似乎是从PythonMATLAB 的“隧道”函数的合适方法:

          http://code.google.com/p/python-matlab-wormholes/

          最大的优势是你可以用它来处理 ndarrays,这在程序的标准输出中是不可能的,如前所述。 (请纠正我,如果您认为这是错误的 - 它会为我省去很多麻烦 :-))

          【讨论】:

            【解决方案8】:

            试试这个 MEX 文件,从 MATLAB 中实际调用 Python,而不是像其他人建议的那样反过来。它提供了相当不错的集成:http://algoholic.eu/matpy/

            你可以很容易地做这样的事情:

            [X,Y]=meshgrid(-10:0.1:10,-10:0.1:10);
            Z=sin(X)+cos(Y);
            py_export('X','Y','Z')
            stmt = sprintf(['import matplotlib\n' ...
            'matplotlib.use(''Qt4Agg'')\n' ...
            'import matplotlib.pyplot as plt\n' ...
            'from mpl_toolkits.mplot3d import axes3d\n' ...
            'f=plt.figure()\n' ...
            'ax=f.gca(projection=''3d'')\n' ...
            'cset=ax.plot_surface(X,Y,Z)\n' ...
            'ax.clabel(cset,fontsize=9,inline=1)\n' ...
            'plt.show()']);
            py('eval', stmt);
            

            【讨论】:

            • +1 感谢您提供出色的解决方案。请考虑将项目托管在 GitHub 上,以便其他人也可以找到它
            • 对于那些感兴趣的人,我刚刚发现了另外两个类似的项目:pythoncallpymex(我自己还没有尝试过)
            【解决方案9】:

            正如@dgorissen 所说,Jython 是最简单的解决方案。

            只需从homepage 安装 Jython。

            然后:

            javaaddpath('/path-to-your-jython-installation/jython.jar')
            
            import org.python.util.PythonInterpreter;
            
            python = PythonInterpreter; %# takes a long time to load!
            python.exec('import some_module');
            python.exec('result = some_module.run_something()');
            result = python.get('result');
            

            有关示例,请参阅 the documentation

            注意:我从未真正使用过 Jython,而且似乎人们可能从 CPython 中了解到的标准库并未在 Jython 中完全实现!

            我测试的小示例运行良好,但您可能会发现您必须将 Python 代码目录添加到 sys.path

            【讨论】:

            • 绝对更容易集成。太糟糕了,到目前为止,您还不能将 Numpy/Scipy/matplotlib 之类的模块与 Jython 一起使用(由于 C 扩展)。在科学计算方面,这些库确实是 Python 的强项
            • 这个问题很难回答。也可以只打开 Python(在 Matlab 之外)并从 REPL shell 写入/读取。我想只有使用 Jython 才能实现无缝集成。然后再次使用 ctypes,将 Octave(而不是 Matlab)集成到 CPython 中可能很容易。
            • (当然,Octave 是 Matlab 的微不足道的替代品。)
            • CPython 允许将embed 其解释器转换为C programs(这是@algoholic 使用MEX-files 所做的)。大部分代码处理 Python 类型(numpy.ndarray 被用作 MATLAB N-D 矩阵的等价物)和 MATLAB 的类型(实际上是 MEX 中的 mxArray)之间的来回转换。
            • 整个事情与您在上面显示的内容相似,只是使用 Python 的 C API 而不是 Jython Java API 来评估解释器中的任意表达式......另外,您可以导入任何已安装的 Python 模块,包括整个PyLab ensemble
            【解决方案10】:

            关于MATLABsystem() 函数的一个鲜为人知(和documented)的事实:在unixoid 系统上,它使用环境变量SHELLMATLAB_SHELL 在启动时给出的任何解释器MATLAB。因此,如果您使用

            启动 MATLAB
            SHELL='/usr/bin/python' matlab
            

            任何后续的system() 调用都将使用Python 而不是您的默认shell 作为解释器。

            【讨论】:

            • 在 Windows 上对我不起作用..(我以通常的方式创建了 env.var.)
            • 嗯,我想你从 Matlab 中检查了变量是否真的设置了?但如果 Matlab 在 Windows 中有不同的标准来决定使用哪个 shell,我不会太惊讶。
            • 是的,我在 MATLAB 中检查了getenv('SHELL')。无论如何,您可能应该提到,不幸的是,这个技巧仅适用于 Linux/Mac
            • +1 这里似乎提到了 SHELL 变量:mathworks.com/help/matlab/ref/matlabunix.html(windows 对应页面,没有)
            【解决方案11】:

            使用 Matlab 2014b 可以调用 python 库directly from matlab。前缀py.被添加到所有数据包名称:

            >> wrapped = py.textwrap.wrap("example")
            
            wrapped = 
            
              Python list with no properties.
            
                ['example']
            

            【讨论】:

            • 这确实是一个很酷的功能 - 但似乎不完整 - 例如我不能那样使用 sklearn 有关详细信息,请参阅我的question
            • py 前缀也可用于用户定义的 python 模块(脚本):例如。 names = py.mymod.search(N)。正确的文档页面是这样的:uk.mathworks.com/help/matlab/matlab_external/…
            【解决方案12】:

            从 Matlab 2014b 开始可以直接调用 Python 函数。 使用前缀 py,然后是模块名称,最后是函数名称,如下所示:

            result = py.module_name.function_name(parameter1);
            

            如果您与 Python 脚本的工作目录不同,请确保在从 Matlab 调用时将脚本添加到 Python 搜索路径。

            查看更多详情here

            【讨论】:

              【解决方案13】:

              正如丹尼尔所说,您可以使用 py.xml 直接从 Matlab 运行 python 命令。命令。要运行任何库,您只需确保 Malab 正在运行您安装库的 python 环境:

              在 Mac 上:

              • 打开一个新的终端窗口;

              • type:哪个python(查找python默认版本安装在哪里);

              • 重启 Matlab;

              • 在命令行中键入:pyv​​ersion('/anaconda2/bin/python')(显然替换为您的路径)。
              • 您现在可以运行默认 python 安装中的所有库。

              例如:

              py.sys.version;

              py.sklearn.cluster.dbscan

              【讨论】:

              • 这是我在这里找到的最简单的解决方案,应该更进一步!
              猜你喜欢
              • 1970-01-01
              • 2015-04-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多