How to call a MATLAB Script in Python 3.9? - python

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.

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.

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.

Related

When to use the terms python shell and python interpreter?

1) I am new to Python and love to learn its core. I have downloaded the python software package and discovered the python.exe application inside. I double clicked it and a balck and white window popped up.
Should I call it a python Interpreter or python Shell?
2) I am learning python online. I came across the terms python tty, python shell and python interpreter. I am satisfied by calling that screen inside the window as a tty(TeleTYpewriter) because we could use only keyboard to work inside and no mouse. But actually that screen has got some intelligence responding to our request. Is python tty an apt term for it?
3) In UNIX, shell is an user interface and command line interpreter, so does python interpreter and python shell are the same.
Python shell lets you use the Python interpreter in interactive mode, just as an OS shell, such as bash, lets you use the OS in interactive mode. You can use the Python interpreter in script mode or batch mode wherein you let the interpreter execute all lines of code in one sequence. It is comparable to writing shell scripts (or batch files in Microsoft Windows).
In your case the screenshot is of a python "shell".
You shouldn't really pay attention to this distinction because in the end everything runs through the python interpreter be it in interactive mode or not.
It is both the python shell and the python interpreter. The shell is where you write your code directly in the CLI, whereas the interpreter is the program that will interpret your code and execute it. Therefore, the interpreter is called in the shell when you write some code, it may also be called when you execute some python code directly from a file.
The customary term for the interactive Python shell is the Python REPL. Many modern interpreters enter a Read-Eval-Print-Loop when you run them interactively, and this term has stuck.
The program which interprets and executes your Python code is the Python interpreter; it can act as a shell, as described above, or run silently and just execute your Python code without any visible user interface of its own, like when you run a script of yours with
python scriptname.py

How can I run my own shell from elisp?

I written a simple shell in python and compiled it with nuitka.
My shell as some simple commands, such as "say string", "braille string", "stop" etc.
This program uses python accessible_output package to communicate with screen reader in windows.
Ok, this works well froma a normal shell, or executing it from windows.
Now, I would like run this program from within emacs, such as normal shell in emacs.
I tried some functions, "start-process", "shell-command", but I can't write commands.
My program displays a prompt, like python interpreter, where I can put my commands.
Elisp is able to run python shells, mysql shells, but I'm unable to run my own shell.
Help!
Emacs has a number of different ways to interact with external program. From your text, I suspect you need to look at comint in the emacs manual and the elisp reference manual. Comint is the low level general shell in a buffer functionality (it is what shell mode uses).
Reading between the lines of your post, I would also suggest you have a look at emacspeak. and speechd.el, both of which are both packages which add speech to emacs. Speechd.el is bare bones and uses speech-dispatcher while emacspeak is very feature rich. The emacspeak package uses a Tcl script which communicates with hardware or software speech servers. It also has a mac version written in python which communicates with the OSX accessiblity (voiceOver) subsystem. Looking at how these packages work will likely give you good examples on how to make yours do what you want.
Take a look at how it's done in the nodejs-repl https://github.com/abicky/nodejs-repl.el/blob/develop/nodejs-repl.el (see line 308)
In python-mode.el, the part in question reads
(with-current-buffer
(apply #'make-comint-in-buffer executable py-buffer-name executable nil (split-string-and-unquote args))
See docstring of make-comint-in-buffer for details.
What about just launching your script from inside an emacs shell buffer?
M-x shell RET /path/to/my/script RET

How to run a python function from a file using python commandline?

I am using python.exe.
I tried:
C:/myfile.py
python C:/myfile.py
python "C:/myfile.py"
It always says "invalid syntax". The code is this one:
https://github.com/paulnasca/paulstretch_python/blob/master/paulstretch_stereo.py#L150
So not sure if the file has bugs or I am doing something wrong.
Your screenshot shows that you are already in the Python interpreter. Trying to run python again will result in an error. Exit the interpreter by hitting CtrlD. Make sure you have downloaded the complete paulstretch_stereo.py file. Put the file in the same directory as the files you want to process. Then, from the Windows command line, run python paulstretch_stereo.py --help and the program's options should print out.
By the way, make sure you have NumPy and SciPy installed, otherwise the program won't run.
What you get when you run python.exe directly is called the interactive interpreter.
The usual way to run a python module is simply providing it as a command-line option to the python process:
python C:/myfile.py
This command is provided from your command-line, not from the interactive interpreter.

launch external shell python instance in shell from python

I'd like to call a separate non-child python program from a python script and have it run externally in a new shell instance. The original python script doesn't need to be aware of the instance it launches, it shouldn't block when the launched process is running and shouldn't care if it dies. This is what I have tried which returns no error but seems to do nothing...
import subprocess
python_path = '/usr/bin/python'
args = [python_path, '&']
p = subprocess.Popen(args, shell=True)
What should I be doing differently
EDIT
The reason for doing this is I have an application with a built in version of python, I have written some python tools that should be run separately alongside this application but there is no assurance that the user will have python installed on their system outside the application with the builtin version I'm using. Because of this I can get the python binary path from the built in version programatically and I'd like to launch an external version of the built in python. This eliminates the need for the user to install python themselves. So in essence I need a simple way to call an external python script using my current running version of python programatically.
I don't need to catch any output into the original program, in fact once launched I'd like it to have nothing to do with the original program
EDIT 2
So it seems that my original question was very unclear so here are more details, I think I was trying to over simplify the question:
I'm running OSX but the code should also work on windows machines.
The main application that has a built in version of CPython is a compiled c++ application that ships with a python framework that it uses at runtime. You can launch the embedded version of this version of python by doing this in a Terminal window on OSX
/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python
From my main application I'd like to be able to run a command in the version of python embedded in the main app that launches an external copy of a python script using the above python version just like I would if I did the following command in a Terminal window. The new launched orphan process should have its own Terminal window so the user can interact with it.
/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python my_python_script
I would like the child python instance not to block the main application and I'd like it to have its own terminal window so the user can interact with it. The main application doesn't need to be aware of the child once its launched in any way. The only reason I would do this is to automate launching an external application using a Terminal for the user
If you're trying to launch a new terminal window to run a new Python in (which isn't what your question asks for, but from a comment it sounds like it's what you actually want):
You can't. At least not in a general-purpose, cross-platform way.
Python is just a command-line program that runs with whatever stdin/stdout/stderr it's given. If those happen to be from a terminal, then it's running in a terminal. It doesn't know anything about the terminal beyond that.
If you need to do this for some specific platform and some specific terminal program—e.g., Terminal.app on OS X, iTerm on OS X, the "DOS prompt" on Windows, gnome-terminal on any X11 system, etc.—that's generally doable, but the way to do it is by launching or scripting the terminal program and telling it to open a new window and run Python in that window. And, needless to say, they all have completely different ways of doing that.
And even then, it's not going to be possible in all cases. For example, if you ssh in to a remote machine and run Python on that machine, there is no way it can reach back to your machine and open a new terminal window.
On most platforms that have multiple possible terminals, you can write some heuristic code that figures out which terminal you're currently running under by just walking os.getppid() until you find something that looks like a terminal you know how to deal with (and if you get to init/launchd/etc. without finding one, then you weren't running in a terminal).
The problem is that you're running Python with the argument &. Python has no idea what to do with that. It's like typing this at the shell:
/usr/bin/python '&'
In fact, if you pay attention, you're almost certainly getting something like this through your stderr:
python: can't open file '&': [Errno 2] No such file or directory
… which is exactly what you'd get from doing the equivalent at the shell.
What you presumably wanted was the equivalent of this shell command:
/usr/bin/python &
But the & there isn't an argument at all, it's part of sh syntax. The subprocess module doesn't know anything about sh syntax, and you're telling it not to use a shell, so there's nobody to interpret that &.
You could tell subprocess to use a shell, so it can do this for you:
cmdline = '{} &'.format(python_path)
p = subprocess.Popen(cmdline, shell=True)
But really, there's no good reason to. Just opening a subprocess and not calling communicate or wait on it already effectively "puts it in the background", just like & does on the shell. So:
args = [python_path]
p = subprocess.Popen(args)
This will start a new Python interpreter that sits there running in the background, trying to use the same stdin/stdout/stderr as your parent. I'm not sure why you want that, but it's the same thing that using & in the shell would have done.
Actually I think there might be a solution to your problem, I found a useful solution at another question here.
This way subprocess.popen starts a new python shell instance and runs the second script from there. It worked perfectly for me on Windows 10.
You can try using screen command
with this command a new shell instance created and the current instance runs in the background.
# screen; python script1.py
After running above command, a new shell prompt will be seen where we can run another script and script1.py will be running in the background.
Hope it helps.

How to properly use PyDev with two different Python versions with scripts that are recalling other python scripts?

The story began with a very strange error while I was running my script from PyDev. Running the same script from outside will not encounter the same problem.
Fatal Python error: Py_Initialize: can't initialize sys standard streams
File "C:\Python26\lib\encodings\__init__.py", line 123
raise CodecRegistryError,\
^
SyntaxError: invalid syntax
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
I was able to find why this is happening: In PyDev I use two different Python versions: 3.1 that is the default installation and 2.6 as the alternative one.
My Windows Environment does not contains PYTHONHOME, CLASSPATH, PYTHONPATH but PyDev does add them.
Now the problem is at one stage my python script does execute another python script using os.system(python second.py) and the second script will fail with the above error.
Now I'm looking to find a way to prevent this issue, issue that is happening because it will run the execute the default python using the settings for the non-default one (added by PyDev).
I do not want to change the standard call (python file.py) but I want to be able to run my script from pydev without problem and being able to use default or alternative python environment.
Any ideas?
I found a solution that seams acceptable specially because it will not interfere with running the scripts on other systems, just to run python -E second.py - this will force Python to ignore PYTHON* environment variables.
I may not be understanding this quite right, but I think you're invoking a script from pydev that works okay, but this script executes another script which requires a different version.
While this would unfortunately be installation-specific, you could use os.system("c:\absolute\path\to\proper\version\of\python.exe second.py").
If PyDev is setting up conflicting environmental variables, you may want to look into subprocess over os.system.
http://docs.python.org/library/subprocess.html#using-the-subprocess-module
This will allow you to invoke a process with a handle, so you can optionally wait for it to terminate. It will also allow you to pass environment variables upon execution.
I believe your call should be:
import sys
os.system(sys.executable+ ' second.py')
So that you guarantee you're using the same interpreter you're currently running and not launching the other one (or did you really mean to use the other interpreter?)

Categories

Resources