2

I have a MATLAB .m file and want a Python.py file to be able to run/call that .m file, however it seems calling MATLAB files using 'import matlab.engine' isn't supported in Python 3.9 (what Im running) and was cut after 3.7

My questions is what is the proper convention to call a MATLAB script in Python 3.9?

EDIT: When I say 'call a MATLAB script', I mean run the script on it's own. Using the .py file to open the MATLAB window kind of defeats the purpose of this project.

7
  • Do you need output from that script? If not, you could just do sth like os.system("matlab script.m") Commented Dec 1, 2020 at 22:27
  • Why does it have to be 3.9? Why can't you use a subprocess or os.system call to run the script? Commented Dec 1, 2020 at 22:28
  • @user8408080 Yes and no, the script outwrites a file which I can just read in to Python no problem. However, using os.system("matlab script.m") just launches the MATLAB window and shows you the script. We're hoping for it to run on it's own. Also, we will likely need to pass in arguments to the .m file Commented Dec 1, 2020 at 22:37
  • @RandomDavis when I use os.system it just launches MATLAB and then you have to run the script from there. we were hoping to have it run automatically through the .py file Commented Dec 1, 2020 at 22:38
  • Use os.system("matlab -batch script.m"), or if you have an older version of MATLAB use os.system("matlab -r 'script.m; exit'"). Commented Dec 1, 2020 at 22:45

2 Answers 2

3

This answer is for Python 3.6 but it should be applicable to 3.9 as well. On a Linux machine (and MacOS, possibly with slight modifications), you can execute a system command which opens MATLAB, runs your script, and then closes MATLAB,

import subprocess

run_matlab = 'matlab -nodisplay -nojvm -nosplash -nodesktop -r "try, test_script, catch e, disp(getReport(e)), exit(1), end, exit(0);"'

subprocess.run(run_matlab, shell=True, check=True)

The purpose of the try-catch block is to properly exit from MATLAB after executing the script test_script in case when the script raises an exception - throws an error. One could instead just exit (exit or quit in MATLAB returns proper exit code by default on those two OS), but with a try-catch block there are more opportunities to fix, notify, or save things when an exception occurs. This may be generally useful when running outside an interactive session.

The rest of the command opens MATLAB with no display of any kind, runs the script test_script, and exits MATLAB - exit(1) signifying an exception was raised, and exit(0) meaning that all went well.

Without the try-catch the command is much simpler,

run_matlab = 'matlab -nodisplay -nojvm -nosplash -nodesktop -r "test_script; exit;"'

On the Python side, I use subprocess.run() (or .call()) since it is newer, and recommended. The option shell means that the command will be executed through the shell. check means that if the run_matlab process (command) throws an error, the Python script will also throw one. The default is False and along with the try-catch block may be used to swiftly ignore crashing code.


As @CrisLuengo said in his comment, starting with MATLAB 2019a (MATLAB 2018b indeed does not have it) there is no need for the elaborated command above. All you need is

run_matlab = 'matlab -batch test_script.m'

Looking at the documentation, -batch invokes all the necessary options, and more.

Sign up to request clarification or add additional context in comments.

4 Comments

The -batch option to MATLAB (new since R2019a I believe) makes all of this simpler. It is no longer needed to use try/catch or exit, and no other command line options are needed either, -nodesktop and so on are all included.
@CrisLuengo good to know. The MATLAB I originally patched it up for was older, couldn't get the newer versions due to outdated OS. I will include your comment tomorrow.
Phenomenal explanation, works like a charm, thank you so much!! Just for anyone else who may stop by this in the future, @CrisLuengo is correct with the -batch saves you the try-catch and as some other answers have said, os.system('matlab command') works in this instance as well.
@mmarion gladly! -batch is indeed much better, I will use it in the newer versions. os.system should work, and will work, it's just that subprocess is newer and better, has more features, and is now recommended.
0

This is more of a hack fix, but you can edit the Python package for the matlab engine on your system and bypass the version checker. Since Python is backwards compatible it shouldn't be a problem, depending on your use case.

Open the following file on your system (or the equivalent file under matlab engine):

vim /usr/lib/python3.9/site-packages/matlab/engine/__init__.py

In that file, change line 31 to include Python 3.9:

_supported_versions = ['2_7', '3_6', '3_7', '3_8', '3_9']

Finally, in line 37, change the version number to a valid version.

    _PYTHONVERSION = '3_7' # or another new, supported version

After this, you should be able to run matlab's engine as if Python 3.9 were supported.

2 Comments

I have python 3.9 installed and am running matlab 2019a. I installed matlab engine and I got the versions error as expected so applied this hack fix. However, the latest PYTHONVERSION change on line 37 results in a "DLL load failed while importing matlabengineforpython3_7: The specified module could not be found." it traces back to: "Python39\lib\importlib__init_.py"
You can change the value from 3_7 to 3_9 on line 37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.