Contents

[TOC]

背景

机器人快速迭代开发场景下主要使用python进行开发,为了避免交付产品暴露python源码,以及能快速打包应用在不同设备上分法安装,因此需要调研一套打包python代码的工具,需要具备如下能力:

  1. 可以对python源码进行处理,避免源码暴露。
  2. 可以方便在不同设备上进行分发。

方案选择

python 部署方案主要集中在源码混淆后部署及源码编译后部署两种方案。以下作简单介绍。

方案对比(cython 与 nuitka )

打包后目录结构

目前语音cython 打包方案,打包目录如下所示。由于是使用 cython 是将目录下所有文件打包成动态库,由于文件内 import 会包含路径因此文件目录无法隐藏,入口文件也无法编译成可执行文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
├── kaiwu_agent_result
   └── kaiwu_agent
       ├── examples
       ├── kaiwu_agent
          ├── __init__.py
          ├── __pycache__
             └── __init__.cpython-310.pyc
          ├── agents
             ├── __init__.py
             ├── __pycache__
             └── agent
          ├── configs
             ├── __init__.py
             ├── __pycache__
             ├── base.so
             ├── brain_agent_react_chat.so
             ├── brain_agent_react_lego_ur.so
             ├── brain_agent_react_lego.so
             ├── brain_agent_react_v1_demo3.so
             ├── brain_agent_react_v2_franka.so
             ├── brain_agent_react.so
             ├── brain_agent_v1v2.so
             ├── brain_agent_v3.so
             ├── chat_agent.so
             ├── commons.so
             ├── config.so
             ├── control_agent.so
             ├── interact_agent.so
             ├── robot_mcts.so
             └── visual_brain_agent.so
          ├── tools
             ├── __init__.py
             ├── __pycache__
             ├── block_tools.so
             ├── interact_agent_server.so
             ├── interact_tools.so
             ├── langgraph_tools.so
             ├── openai_tools.so
             └── search_tools.so
          └── utils
              ├── __init__.py
              ├── __pycache__
              ├── common.so
              ├── env.so
              ├── image_process.so
              ├── kaiwu_message.so
              ├── lego
              ├── logger.so
              ├── openai_support.so
              ├── orbbec_camera.so
              └── voice.so
       ├── main_release.py
       ├── main_release.so
       ├── main.so
       ├── requirements_interact.txt
       ├── requirements.txt
       └── setup.so
└── robot_voice_result
    └── robot_voice
        ├── configs
        ├── fake_server.so
        ├── README_RELEASE.md
        ├── requirements
           ├── develop.txt
           └── install.txt
        ├── requirements.txt
        ├── robot_voice
           ├── __init__.py
           ├── __pycache__
              └── __init__.cpython-310.pyc
           ├── listener
              ├── __init__.py
              ├── __pycache__
              ├── sbus_controler.so
              └── xf_voice
           ├── tool
              ├── __init__.py
              ├── __pycache__
              ├── audioPlayer.so
              ├── cosyvoice_pb2_grpc.so
              ├── cosyvoice_pb2.so
              ├── tencent
              ├── tts_player.so
              ├── xf_translate.so
              ├── xf_tts.so
              └── xunfei
           └── utils
               ├── __init__.py
               ├── __pycache__
               ├── check_xf.so
               ├── common.so
               ├── log.so
               └── voice_server.so
        ├── server_ros2.py
        ├── server_ros2.so
        └── server.so

以下使用 nuitka 打包(使用accelerated模式,相关优劣后面会有介绍),可以打包为一个可执行文件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
├── kaiwu_agent_result
│   ├── examples
│   │   ├── music
│   │   └── rag
│   ├── main_release.bin
│   └── requirements.txt
├── requirements-all.txt
└── robot_voice_result
    ├── configs
    │   ├── __init__.py
    │   ├── server_cfg.py
    │   └── voice
    ├── requirements.txt
    └── server_ros2.bin

Nuitka 方案存在问题和风险

动态加载文件无法识别编译

  1. 动态修改Python的模块搜索路径

    1
    2
    3
    4
    5
    
    import os,sys
    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
    import grpc
    
    import cosyvoice_pb2 as cosyvoice__pb2
    

    需要改为如下方式:

    1
    2
    
    import grpc
    import robot_voice.tool.cosyvoice_pb2 as cosyvoice__pb2
    
  2. gi 动态调用C库需要在运行时指定动态库路径

    1
    2
    3
    
    import gi
    gi.require_version('Gst', '1.0')
    from gi.repository import Gst
    

    运行时需要指定

    1
    
    export GST_PLUGIN_PATH=/home/ps/miniconda3/envs/rtp_player/lib/gstreamer-1.0/
    

standalone&onefile 模式编译问题

standalone&onefile 模式会将Python 应用程序及其所有依赖项打包到一个独立的文件夹中。这个文件夹包含了运行应用程序所需的所有内容,包括 Python 解释器、库文件和你的代码。

Standalone:生成一个包含多个文件的文件夹,直接从文件夹中运行,无需解压。

One-file:生成一个单独的可执行文件,运行时会解压到临时目录。

  • 编译时间长编译文件大复杂工程编译失败/

accelerated 模式编译问题

accelerated 模式 会在你的 Python 安装环境中运行,并依赖于该环境。

  • 依然面临python环境管理问题

  • accelerated 模式数据需要用户手动拷贝

Nuitka 使用

Nuitka 常用编译指令介绍

设置编译模式

编译模式: 默认模式是 accelerated。

  • accelerated 模式会在你的 Python 安装环境中运行,并依赖于它。

  • standalone 模式会创建一个包含可执行文件的文件夹来运行它。

  • onefile 模式会生成一个单独的可执行文件以便部署。

  • app 模式类似于 onefile,但在 macOS 上不推荐使用。

  • module 模式会生成一个模块

  • package 模式还会包含所有子模块和子包。

  • Dll 模式目前正在开发中,尚未对用户开放。

查看使用插件

某些复杂的第三方库(如 PyQt5、TensorFlow、PyTorch 等)需要特殊的处理才能正确打包。插件可以自动处理这些库的依赖关系,减少打包问题。

以下仅列出部分。

  • nuitka --plugin-list 查看支持的插件,结果如下:

    1
    2
    3
    4
    5
    
     matplotlib        Required for 'matplotlib' module.
     pyqt5             Required by the PyQt5 package.
     transformers      Provide implicit imports for transformers package.
     xxx
     xxx
    
  • --plugin-enable=pyqt5使用插件

控制导入的模块

以下仅列出部分。

  • --follow-imports

    导入所有被导入的模块。在standalone&onefile模式下默认开启,否则关闭。

  • --nofollow-imports

    不递归深入(导入)到任何导入的模块,这将覆盖所有其他包含选项,并且不能用于standalone&onefile模式。默认关闭。

  • --follow-import-to=MODULE/PACKAGE

    可以多次给出。默认为空。

  • --nofollow-import-to=MODULE/PACKAGE

    可以多次给出。默认为空。

数据文件

accelerated 模式下只有商业版才能使用。

以下仅列出部分。

  • --include-package-data=PACKAGE

  • --include-data-files=DESC

  • --include-data-dir=DIRECTORY

nuitka编译打包demo

独立安装包(standalone&onefile 模式)

依赖环境安装包 (accelerated 模式)

后续计划

  1. 先在语音软件包上进行部署尝试后续扩展到300#其他软件包。
  2. python 依赖冲突问题解决? (是否基于nuitka 将有版本冲突的包编译到可执行文件中)。