从Matlab调用Anaconda env时如何解决numpy导入错误

时间:2018-06-20 14:56:04

标签: matlab numpy anaconda python-3.5 importerror

我想从Matlab(在Windows 7计算机上)执行Python脚本。必需的库安装在Anaconda虚拟环境中。从命令行运行脚本时,它可以完美运行。

从Matlab调用脚本时,如下所示: [status,commandOut] = system('C:/Users/user/AppData/Local/Continuum/anaconda3/envs/tf/python.exe test.py');

或使用shell命令,出现导入错误:

commandOut =

'Traceback (most recent call last):
   File "C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\lib\site-packages\numpy\core\__init__.py", line 16, in <module>
     from . import multiarray
 ImportError: DLL load failed: The specified path is invalid.

 During handling of the above exception, another exception occurred:

 Traceback (most recent call last):
   File "test.py", line 2, in <module>
     import numpy as np
   File "C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\lib\site-packages\numpy\__init__.py", line 142, in <module>
     from . import add_newdocs
   File "C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\lib\site-packages\numpy\add_newdocs.py", line 13, in <module>
     from numpy.lib import add_newdoc
   File "C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\lib\site-packages\numpy\lib\__init__.py", line 8, in <module>
     from .type_check import *
   File "C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\lib\site-packages\numpy\lib\type_check.py", line 11, in <module>
     import numpy.core.numeric as _nx
   File "C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\lib\site-packages\numpy\core\__init__.py", line 26, in <module>
     raise ImportError(msg)
 ImportError: 
 Importing the multiarray numpy extension module failed.  Most
 likely you are trying to import a failed build of numpy.
 If you're working with a numpy git repo, try `git clean -xdf` (removes all
 files not under version control).  Otherwise reinstall numpy.

 Original error was: DLL load failed: The specified path is invalid.

我已经将默认的Matlab Python版本更改为Anaconda env,但没有更改:

   version: '3.5'
executable: 'C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\python.exe'
   library: 'C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf\python35.dll'
      home: 'C:\Users\user\AppData\Local\Continuum\anaconda3\envs\tf'
  isloaded: 1

仅运行我的测试脚本而无需导入numpy作品。重新加载numpy(py.importlib.import_module('numpy');)无效,但引发了与以前相同的错误。

有人知道如何解决此问题吗?

3 个答案:

答案 0 :(得分:1)

因此,在获得Matlab支持后,我发现Matlab依赖于路径环境(使用虚拟环境时故意未设置的路径),因此numpy在Matlab中调用时找不到必要的路径(即使调用包含虚拟环境的路径)。

解决方案是从虚拟环境中(通过命令行)调用Matlab,或者在路径环境中手动添加缺少的路径。 也许这些信息可以帮助其他人。

答案 1 :(得分:0)

第一种方法

您可以使用以下方式更改python解释器:

pyversion("/home/nibalysc/Programs/anaconda3/bin/python");

并使用以下命令进行检查:

pyversion();

您也可以在

中执行此操作
  

startup.m

文件放在项目文件夹中,每次从该文件夹启动MATLAB时,python解释器都会自动更改。

现在您可以尝试使用:

py.importlib.import_module('numpy');

阅读有关如何在MATLAB中使用集成python的文档:

Call user defined custom module
Call modified python module

替代方法

另一种方法是创建一个

  

matlab_shell.sh

具有以下内容的文件,这基本上是安装anaconda时来自.bashrc的附加代码,并询问安装程序是否应修改.bashrc文件:

#!/bin/bash
__conda_setup="$(CONDA_REPORT_ERRORS=false '$HOME/path/to/anaconda3/bin/conda' shell.bash hook 2> /dev/null)"
if [ $? -eq 0 ]; then
    \eval "$__conda_setup"
else
    if [ -f "$HOME/path/to/anaconda3/etc/profile.d/conda.sh" ]; then
        CONDA_CHANGEPS1=false conda activate base
    else
        \export PATH="$HOME/path/to/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda init <<<
# >>> conda initialize >>>
# !! Contents within this block are managed by 'conda init' !!
__conda_setup="$('$HOME/path/to/anaconda3/bin/conda' 'shell.bash' 'hook' 2> /dev/null)"
if [ $? -eq 0 ]; then
    eval "$__conda_setup"
else
    if [ -f "$HOME/path/to/anaconda3/etc/profile.d/conda.sh" ]; then
        . "$HOME/path/to/anaconda3/etc/profile.d/conda.sh"
    else
        export PATH="$HOME/path/to/anaconda3/bin:$PATH"
    fi
fi
unset __conda_setup
# <<< conda initialize <<<
conda activate base
eval $2

然后,您需要在运行MATLAB之前或在MATLAB本身中设置MATLAB_SHELL环境变量。我认为最好的办法是也可以在startup.m文件中执行以下操作:

setenv("MATLAB_SHELL", "/path/to/matlab_shell.sh");

然后,您可以使用system(...)函数在安装了所有模块的情况下运行conda python ...

字符串符号:

system("python -c ""python code goes here"");

字符符号:

system('python -c "python code goes here"');

希望这会有所帮助!

答案 2 :(得分:0)

首先,如果您像常规系统命令([status, commandOut] = system('...python.exe test.py')一样执行Python脚本, pyversion(以及自{R2019b起,pyenv)完全无效。仅当您使用py.集成(如下面的代码)(在大多数情况下,这是一种更好的方法)时,才有意义。

当前(我使用R2019b更新5)存在很多陷阱,可能会导致与您类似的问题。我建议从以下内容开始:

  1. 创建一个新的干净的conda环境:
conda create -n test_py36 python=3.6 numpy
  1. 创建以下虚拟demo1.py
def dummy_py_method(x):
    return x+1

  1. 创建以下run_py_code.m
function  run_py_code()

% explicit module import sometimes show more detailed error messages
py.importlib.import_module('numpy');

% to reloads if there would be any changes:
pymodule = py.importlib.import_module('demo1');
py.importlib.reload(pymodule);

% passing data back and forth
x = rand([3 3]);
x_np = py.numpy.array(x);
y_np=pymodule.dummy_py_method(x_np);
y = double(y_np);
disp(y-x);
  1. 创建以下before_first_run.m
setenv('PYTHONUNBUFFERED','1');

setenv('path',['C:\Users\username\Anaconda3\envs\test_py36\Library\bin;'...
               getenv('path')]);

pe=pyenv('Version','C:\users\username\Anaconda3\envs\test_py36\pythonw.exe',...
         'ExecutionMode','InProcess'...
         ); 

% add "demo1.py" to path
py_file_path = 'W:\tests\Matlab\python_demos\call_pycode\pycode';
if count(py.sys.path,py_file_path) == 0
    insert(py.sys.path,int32(0),py_file_path);
end

  1. 首先运行before_first_run.m,然后运行run_py_code.m

注意:

  • 正如this answer中已经提到的,一个关键点是在启动python之前将包含必要dll文件的文件夹添加到%PATH%。这可以通过使用Matlab的setenv来实现。通常,应该添加Library\bin

  • 尝试干净的官方支持的CPython发行版(例如CPython 3.6.8)是一个好主意。仅安装numpy(python -m pip install numpy)。根据我的经验,在这种情况下,setenv不是必需的。

  • 对我来说,OutOfProcess模式被证明是越野车。因此,我建议显式设置InProcess模式(对于R2019b之前的版本,OutOfProcess选项以及pyenv都不存在)。

  • 不要将上面的两个.m文件连接成一个文件-py.importlib语句似乎已预先执行,因此与pyenv冲突。

    li>