78

I need to call a Python function from MATLAB. how can I do this?

6
  • 2
    Does MATLAB have support for sockets? Commented Nov 10, 2009 at 17:24
  • 1
    apparently it does have socket support code.google.com/p/msocket if that helps Commented Nov 10, 2009 at 17:36
  • 1
    If we are adding options: github.com/kw/pymex Commented Jan 17, 2013 at 8:41
  • Relevant to the opposite direction, of translating Matlab code to Python (with some calling interfaces mentioned too): stackoverflow.com/q/9845292/1959808 Commented Sep 25, 2017 at 0:24
  • Why not accept an answer? The "right" answer didn't exist when the question was asked, but it does now: stackoverflow.com/a/29189167/1959808 Commented Sep 25, 2017 at 0:30

13 Answers 13

48

I had a similar requirement on my system and this was my solution:

In MATLAB there is a function called perl.m, which allows you to call perl scripts from MATLAB. Depending on which version you are using it will be located somewhere like

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

Create a copy called python.m, a quick search and replace of perl with python, double check the command path it sets up to point to your installation of python. You should now be able to run python scripts from MATLAB.

Example

A simple squared function in python saved as "sqd.py", naturally if I was doing this properly I'd have a few checks in testing input arguments, valid numbers etc.

import sys

def squared(x):
    y = x * x
    return y

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

Then in MATLAB

>> r=python('sqd.py','3.5')
r =
12.25
>> r=python('sqd.py','5')
r =
25.0
>>
Sign up to request clarification or add additional context in comments.

6 Comments

perl just makes a system call to execute the Perl script - there is no transfer of data between the Perl script and MATLAB apart from "the results of attempted Perl call to result and its exit status to status." - mathworks.com/access/helpdesk/help/techdoc/ref/perl.html
I agree it just makes a system call but why make things complicated with mex functions and sockets if it isn't required? At a simple level the call to python does have a simple data transfer. I'll update the answer with an example.
+1 - The MATLAB example code looks great - could you post (code/link) python.m? What are the limitations of the data returned - only scalar?
Can we pass also array as argument to the python file?
Note that this works but it's a hack, there's a lot of paths that don't really go anywhere, e.g., fullfile(matlabroot, 'sys\python\win32\bin\'); points to a path that isn't really there, there aren't any python error messages defined, so the message('MATLAB:python:<>') error messages won't work in the CTRL+F'd Perl.m
|
30

With Matlab 2014b python libraries can be called directly from matlab. A prefix py. is added to all packet names:

>> wrapped = py.textwrap.wrap("example")

wrapped = 

  Python list with no properties.

    ['example']

2 Comments

This is indeed a cool Feature - but seems to be incomplete - for example I can not use sklearn that way For Details see my question.
The py prefix can be used for user defined python modules (scripts) as well: eg. names = py.mymod.search(N). The right documentation page is this: uk.mathworks.com/help/matlab/matlab_external/…
20
+50

Try this MEX file for ACTUALLY calling Python from MATLAB not the other way around as others suggest. It provides fairly decent integration : http://algoholic.eu/matpy/

You can do something like this easily:

[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);

2 Comments

+1 thank you for an excellent solution. Please consider hosting the project on GitHub, so that others might find it as well
For those interested, I just found two other similar projects: pythoncall and pymex (haven't tried them myself yet)
14

You could embed your Python script in a C program and then MEX the C program with MATLAB but that might be a lot of work compared dumping the results to a file.

You can call MATLAB functions in Python using PyMat. Apart from that, SciPy has several MATLAB duplicate functions.

But if you need to run Python scripts from MATLAB, you can try running system commands to run the script and store the results in a file and read it later in MATLAB.

Comments

11

As @dgorissen said, Jython is the easiest solution.

Just install Jython from the homepage.

Then:

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');

See the documentation for some examples.

Beware: I never actually worked with Jython and it seems that the standard library one may know from CPython is not fully implemented in Jython!

Small examples I tested worked just fine, but you may find that you have to prepend your Python code directory to sys.path.

5 Comments

it is definitely easier to integrate. Too bad that as of yet, you can't use modules like Numpy/Scipy/matplotlib with Jython (on the account of C extensions). Those libraries are really Python's strong point when it comes to scientific computing
It's difficult to answer the question. One could just open Python (out of Matlab) and write to/read from the REPL shell, too. I guess a seamless integration will only be possible with Jython. Then again using ctypes it might be easy to integrate Octave, but not Matlab, into CPython.
(Granted, Octave is a puny replacement for Matlab.)
CPython allows to embed its interpreter into C programs (which is what @algoholic has done using MEX-files). The bulk of the code deals with converting back and forth between Python types (numpy.ndarray was used as the equivalent of MATLAB N-D matrices), and MATLAB's types (really mxArray in MEX).
The whole thing is similar to what you've shown above, only using Python's C API instead of Jython Java API to evaluate arbitrary expressions in the interpreter... Plus you can import any installed Python module, including the whole PyLab ensemble
10

The simplest way to do this is to use MATLAB's system function.

So basically, you would execute a Python function on MATLAB as you would do on the command prompt (Windows), or shell (Linux):

system('python pythonfile.py')

The above is for simply running a Python file. If you wanted to run a Python function (and give it some arguments), then you would need something like:

system('python pythonfile.py argument')

For a concrete example, take the Python code in Adrian's answer to this question, and save it to a Python file, that is test.py. Then place this file in your MATLAB directory and run the following command on MATLAB:

system('python test.py 2')

And you will get as your output 4 or 2^2.

Note: MATLAB looks in the current MATLAB directory for whatever Python file you specify with the system command.

This is probably the simplest way to solve your problem, as you simply use an existing function in MATLAB to do your bidding.

2 Comments

This is what I had been doing, but I'm running into a mysterious problem—one of the arguments to my python script is a file. When called from MATLAB, the python script can't find the file (despite all scripts being in the same directory as the file, and despite specifying the full path in the MATLAB script). Maddening.
The suggestions looks great, but I get the error message "'python' is not recognized as an internal or external command, operable program or batch file. "
8

Starting from Matlab 2014b Python functions can be called directly. Use prefix py, then module name, and finally function name like so:

result = py.module_name.function_name(argument1, argument2, ...);

Make sure to add the script to the Python search path when calling from Matlab if you are in a different working directory than that of the Python script.


Introduction

The source code below explains how to call a function from a Python module from a Matlab script.

It is assumed that MATLAB and Python are already installed (along with NumPy in this particular example).

Exploring the topic I landed on this link (MATLAB 2014b Release Notes) on the MathWorks website which indicated that it is possible starting from Matlab R2014b.

Instructions

In the example below it is assumed the current working directory will have the following structure:

our_module
  |
  +-> our_script.py
matlab_scripts
  |
  +-> matlab_script.m

Start with a simple script our_module/our_script.py:

import numpy

def our_function(text):
    print('%s %f' % (text, numpy.nan))

It has one function which prints the string passed to it as a parameter, followed by NaN (not-a-number) value.

Keep it in its own directory our_module.

Next, go to Matlab and navigate to the current working directory where the Python module (our_module) is located.

Call the function from the Python module with the following statement:

py.our_module.our_script.our_function('Hello')

This will have the expected outcome:

>> py.our_module.our_script.our_function('Hello')
Hello nan
>>

However, a matlab_script.m file in a matlab_scripts directory (created next to the our_module directory) with only the above statement will result in the following outcome:

>> matlab_script
Undefined variable "py" or class "py.our_module.our_script.our_function".

Error in matlab_script (line 1)
py.our_module.our_script.our_function('Hello')
>>

Looking for the solution I found a page entitled Undefined variable "py" or function "py.command" which helped to troubleshoot this error.

Assuming there is no typo in the script it recommends adding the base directory to Python's search path.

Therefore, the correct content of the Matlab script should be:

[own_path, ~, ~] = fileparts(mfilename('fullpath'));
module_path = fullfile(own_path, '..');
python_path = py.sys.path;
if count(python_path, module_path) == 0
    insert(python_path, int32(0), module_path);
end
py.our_module.our_script.our_function('Hello')

It obtains the location of the Python module, finds the base path of that module, accesses the Python search path, checks if the base path is already included and inserts it otherwise.

Running the corrected script will result in the same expected output as before.

Here is another helpful link to get you going.

Comments

4

I've adapted the perl.m to python.m and attached this for reference for others, but I can't seem to get any output from the Python scripts to be returned to the MATLAB variable :(

Here is my M-file; note I point directly to the Python folder, C:\python27_64, in my code, and this would change on your system.

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

EDIT :

Worked out my problem the original perl.m points to a Perl installation in the MATLAB folder by updating PATH then calling Perl. The function above points to my Python install. When I called my function.py file, it was in a different directory and called other files in that directory. These where not reflected in the PATH, and I had to easy_install my Python files into my Python distribution.

Comments

4

A little known (and little documented) fact about MATLAB's system() function: On unixoid systems it uses whatever interpreter is given in the environment variable SHELL or MATLAB_SHELL at the time of starting MATLAB. So if you start MATLAB with

SHELL='/usr/bin/python' matlab

any subsequent system() calls will use Python instead of your default shell as an interpreter.

4 Comments

didn't work for me on Windows.. (I created the env. var. the usual way)
Hmm, I suppose you checked from within Matlab that the variable was really set? But I would not be too surprised if Matlab had different criteria in Windows to decide which shell to use.
yes I checked getenv('SHELL') within MATLAB.. Anyway you should probably mention it that this trick is unfortunately Linux/Mac only
+1 there seems to be a mention of SHELL variable here: mathworks.com/help/matlab/ref/matlabunix.html (the windows counterpart page, doesnt have it)
3

Since MATLAB seamlessly integrates with Java, you can use Jython to write your script and call that from MATLAB (you may have to add a thin pure JKava wrapper to actually call the Jython code). I never tried it, but I can't see why it won't work.

Comments

3

Like Daniel said you can run python commands directly from Matlab using the py. command. To run any of the libraries you just have to make sure Malab is running the python environment where you installed the libraries:

On a Mac:

  • Open a new terminal window;

  • type: which python (to find out where the default version of python is installed);

  • Restart Matlab;

  • type: pyversion('/anaconda2/bin/python'), in the command line (obviously replace with your path).
  • You can now run all the libraries in your default python installation.

For example:

py.sys.version;

py.sklearn.cluster.dbscan

1 Comment

This is the simplest solution I have found here, it should be much further up!
1

This seems to be a suitable method to "tunnel" functions from Python to MATLAB:

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

The big advantage is that you can handle ndarrays with it, which is not possible by the standard output of programs, as suggested before. (Please correct me, if you think this is wrong - it would save me a lot of trouble :-) )

Comments

-1

Since Python is a better glue language, it may be easier to call the MATLAB part of your program from Python instead of vice-versa.

Check out Mlabwrap.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.