Matlab编译为python在docker中运行

0. 准备

本文只讨论将matlab封装成python,并在docker中运行python脚本的情况

要让matlab运行在docker里,你需要:

  • 在本机,你需要安装matlab和对应版本的matlab compiler runtime(简称mcc),在这里下载

  • 需要准备一个和你本机的matlab版本相同的MCC的Docker镜像,所幸有现成的,在这里

1. 将matlab函数编译为python

我的matlab运行于mac环境中,版本为2019b

1. 封装函数

没什么好说的,我在这里封装了一个名为algorithm的函数,再编写一个调用这个函数的脚本:
Matlab编译为python在docker中运行_第1张图片

2. 编译

Matlab编译为python在docker中运行_第2张图片
命令窗口输入deploytool,选择Library Compiler
Matlab编译为python在docker中运行_第3张图片

  1. 选则TYPE框内的Python Package
  2. 点击EXPORTED FUNCTIONS框的➕,添加所需的函数(不要添加脚本,会提示错误)
  3. 在下方的Samples框内点击Add Existing Sample,添加编写的调用脚本(不添加sample不会影响生成,就是没有调用参考了,也没有生成编译后脚本的单元测试了)
  4. 点击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']}

就是把在linux环境下调用的环境变量指向一个我们自定的位置

2. 让编译后的脚本再docker下可用

1. 文件结构

Matlab编译为python在docker中运行_第4张图片

  • 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的内容,所以在调用脚本时需要换回来,调用结束后再恢复.

你可能感兴趣的:(DevOps)