Make it works(4) Matlab编译为python
2020-05-03 本文已影响0人
默而识之者
0. 准备
本文只讨论将matlab封装成python,并在docker中运行python脚本的情况
要让matlab运行在docker里,你需要:
-
在本机,你需要安装matlab和对应版本的matlab compiler runtime(简称mcc),在这里下载
-
需要准备一个和你本机的matlab版本相同的MCC的Docker镜像,所幸有现成的,在这里
1. 将matlab函数编译为python
我的matlab运行于mac环境中,版本为2019b
1. 封装函数
没什么好说的,我在这里封装了一个名为algorithm的函数,再编写一个调用这个函数的脚本:
2. 编译
命令窗口输入
deploytool
,选择Library Compiler
- 选则
TYPE
框内的Python Package
- 点击
EXPORTED FUNCTIONS
框的➕,添加所需的函数(不要添加脚本,会提示错误)- 在下方的
Samples
框内点击Add Existing Sample
,添加编写的调用脚本(不添加sample不会影响生成,就是没有调用参考了,也没有生成编译后脚本的单元测试了)- 点击
Package
按钮开始编译,一定要安装MCC才行,编译成功会自动打开成果文件夹,编译失败则会在在编译见面有惊叹号.
3. 修改编译成果
mcc在docker运行时需要LD_LIBRARY_PATH
这个环境变量为/opt/mcr/v97/runtime/glnxa64:/opt/mcr/v97/bin/glnxa64:/opt/mcr/v97/sys/os/glnxa64:/opt/mcr/v97/extern/bin/glnxa64
(matlab2019b),然而这个设置是侵入性的,这个环境变量会让相当数量的常用工具无法使用,所以需要修改一下生成的文件:
在生成的包中__init__.py
文件下,修改:
PLATFORM_DICT = {'Windows': ['PATH','dll',''], 'Linux': ['LD_LIBRARY_PATH','so','libmw'], 'Darwin': ['DYLD_LIBRARY_PATH','dylib','libmw']}
为
PLATFORM_DICT = {'Windows': ['PATH','dll',''], 'Linux': ['MYLD_LIBRARY_PATH','so','libmw'], 'Darwin': ['DYLD_LIBRARY_PATH','dylib','libmw']}
就是把该环境变量指向一个我们自定义的位置
2. 让编译后的脚本再docker下可用
1. 文件结构
- alogrithm/setup.py和alogrithm/alogrithm是编译后的包和其安装脚本
- run.py是如何调用该包的脚本
- run.sh是调用run.py的脚本
2. Dockerfile
FROM demartis/matlab-runtime:R2019b
# 将所需的文件拷到指定目录,我这为了方便拷到了根目录
COPY ./algorithm/ /
# 给MYLD_LIBRARY_PATH这个我们自定义的环境变量赋值,供脚本安装时使用
ENV MYLD_LIBRARY_PATH /opt/mcr/v97/runtime/glnxa64:/opt/mcr/v97/bin/glnxa64:/opt/mcr/v97/sys/os/glnxa64:/opt/mcr/v97/extern/bin/glnxa64
# 将LD_LIBRARY_PATH指向正确的位置
ENV LD_LIBRARY_PATH=/usr/lib
# 1. 修改为国内源,并添加了一个源,里面有高版本python
# 2. 一定要安装libpython3.7,否则无法运行脚本
# 3. 最后一步因为安装了多个版本的python(2.7,3.7,3.8),所以要指定版本,因为matlab2019b不支持python3.8
RUN sed -i s@/security.debian.org/@/mirrors.163.com/@g /etc/apt/sources.list && \
sed -i s@/deb.debian.org/@/mirrors.163.com/@g /etc/apt/sources.list && \
echo "deb http://mirrors.163.com/debian/ testing main">>/etc/apt/sources.list && \
apt-get update && \
apt-get install python3-distutils -y && \
apt install --reinstall libpython3.7 && \
apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \
python3.7 /setup.py install
3. 运行脚本
run.py的内容与自动生成的sample
内容一致
import algorithm
import matlab
my_algorithm = algorithm.initialize()
my_algorithm.algorithm("xxxx.xxx", nargout=0)
my_algorithm.terminate()
run.sh
# 运行前先切换回来
export LD_LIBRARY_PATH=/opt/mcr/v97/runtime/glnxa64:/opt/mcr/v97/bin/glnxa64:/opt/mcr/v97/sys/os/glnxa64:/opt/mcr/v97/extern/bin/glnxa64 && \
python3.7 /run.py && \
# 运行后再换回去
export LD_LIBRARY_PATH=/usr/lib
# ...做其他的事
因为编译后的脚本调用的二进制库在使用时会用到LD_LIBRARY_PATH的内容,所以在调用脚本时需要换回来,调用结束后再恢复.