Changing Python Environment used by MATLAB

103 views (last 30 days)
Furqan Hashim
Furqan Hashim on 9 Aug 2020
Commented: Jason Kulpe on 17 Dec 2021
I have mutiple python enviroments on a windows server. I need to change the Python enviroment that MATLAB is using. MATLAB version that I am using is 2017b and I've used the command pyversion('/path/to/python/venv') to change python environment being used by MATLAB. This command gives an error
Python is loaded. The version cannot be changed in this MATLAB session. To change the version, restart MATLAB, and then call 'pyversion'.
To deal with the above error I've made changes to startup.m file by changing two variables
pyPath = '/path/to/python/venv';
pyLibPath = [pyPath 'Lib\site-packages\projects'];
After making changes and restarting MATLAB I get an error
Unable to set Python environment to /path/to/python/venv in this session.
Please restart MATLAB!
I suspect that if results from command py.sys.path contains any path with directory that refers to old python environment I won't be able to set new Python environment. E.g. if the result from command py.sys.path is
['/path/to/python/venv', '','/path/to/python/old_venv']
I need to remove '/path/to/python/old_venv' using remove(py.sys.path, '/path/to/python/old_venv'). I did that but when I restart MATLAB after doing that I see that output from py.sys.path does not change as it still contains '/path/to/python/old_venv'. To be sure that older python paths are removed from py.sys.path I've ran following commands in new Python environment
import sys
sys.path
Output from above doesnot contain any paths from older Python environment.
Can someone provide a solution on how can I change the Python environment being used by MATLAb?
I've mentioned all the things that I've tried.
  2 Comments
Arturo Pino
Arturo Pino on 4 Aug 2021
I'm dealing with this exact same issue. After initially setting a python environment, I can't reset even after restarting matlab because it seems to default to the environment I gave it several sessions ago. No matter what I do, it always will load the previously loaded environment and tells me to restart matlab because the environment is already set. So frustrating!
Jason Kulpe
Jason Kulpe on 17 Dec 2021
I have never been so frustrated, in 15 years of MATLAB usage and wanted to share my experience as its very similar. . I have unit tests running, via Jenkins, in a batch startup mode. My tests were failing only on Mac; windows OK. Running the exact same test commands on my local Mac worked fine so test failing only on a remote system. Per finding this article I have realized the issue and fixed everything. Thanks for the comments and answers!
Original way (tests worked)
% Code in file1.m
pyenv('Version', my_python_dist)
% Execute file2 from inside file1
file2
% This code is in file2.m
% Insert the paths outlined above into the python path
for idx = 1:length(modpaths)
P = py.sys.path;
modpath = modpaths(idx);
if count(P, modpath) == 0
insert(P, int32(0), modpath);
end
end
New way - (test failure). I wanted to simplify the commands and reorganize the code. The py.sys.path command, after the pyenv setup, turned out to be the culprit. Perhaps the MATLAB interpreter notice the py.sys usage and defaulted (and loaded) to the system python.
% Code in file1.m
pyenv('Version', my_python_dist)
% This code is in file1.m
% Insert the paths outlined above into the python path
for idx = 1:length(modpaths)
P = py.sys.path;
modpath = modpaths(idx);
if count(P, modpath) == 0
insert(P, int32(0), modpath);
end
end

Sign in to comment.

Answers (1)

Yongjian Feng
Yongjian Feng on 11 Aug 2021
virtualenv is challenging. Is it possible to avoid virtualenv?
  4 Comments
Gabriel Bergqvist
Gabriel Bergqvist on 30 Aug 2021
Edited: Gabriel Bergqvist on 30 Aug 2021
Completing the above answer, here's some related advice for what usually comes next:
function safe_add_py_path(new_path)
if sum(cellfun(@string, cell(py.sys.path)) == new_path) == 0
insert(py.sys.path, int64(0), new_path);
end
end
safe_add_py_path("/path/to/my/python/source_root";
module_hello = py.importlib.import_module("hello");
my_hello_object = module_hello.HelloClass(params_to_the_init_function_here);
python_data_type_result = my_hello_object.some_hello_method(python_data_type_params)
After that, you probably want to start passing increasingly complex data between Matlab and Python, in which case the difference between the two worlds' data types is going to be a major source of trouble, unless properly handled. If that is the case, I recommend using string-formatted JSON objects between the two worlds. Both Matlab and Python happens to be rather good at reading/writing JSON-strings, so make yourself some nice little wrappers for whatever datatypes you find useful, and/or "stringify" it before sending it to Python (the same goes for the other way as well). Note: This is for advanced use-cases with complex data structures. No need to "stringify" anything for basic use-cases. Example of how to stringify a struct s with JSON-encodable Matlab data on the Matlab side, typically right before sending to it Python:
function stringify_struct = stringify_struct(s)
stringify_struct = string(jsonencode(s));
end
(On the Python-side, use json.dumps and json.loads)
Gabriel Bergqvist
Gabriel Bergqvist on 30 Aug 2021
Edited: Gabriel Bergqvist on 30 Aug 2021
One more thing, seemingly unrelated actions may load the pyenv for you. For example, setting a breakpoint may or may not load the pyenv, depending on exactly in which file you set it (typically setting it in Matlab's internal read-only files may trig this, e.g. getPropertyGroups.m). This makes trying to understand exactly when the pyenv is loaded quite difficult, since the action of setting breakpoints itself may load pyenv. In short, assume pyenv will be loaded at any point during startup of AppDesigner, your App, or the debugger for that matter.
Hence, you may need to explicitly load your preferred pyenv (with whatever config you need) before starting things like AppDesigner, your App, or similar.
From a developer's perspective, I think this should be considered a bug.
I also suspect that certain ways of calling Matlab code may trig the pyenv loading as well. For example, running some commands as a .m function file may load pyenv prematurely (i.e. break the execution) while the same code executed as a .m script file always works (script file = without a function declaration). There is determinism to when Matlab choses to freeze your pyenv for you, albeit absolutely zero transparency or apparent logic. This makes it very hard to use the pyenv functionality in Matlab for more advanced use-cases, unfortunately. It is possible, but bordering reverse-engineering.

Sign in to comment.

Products


Release

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!