pyinstaller打包相关问题与最佳实践

pyinstaller是一个python代码打包工具,打包后,可以避免代码暴露,也可以避免函数库的依赖。

0.推荐的最佳实践:

01. 将build,dist目录另行放置:

这样可以防止代码备份时备份进无关的文件

#将dist目录设置到指定位置
pyinstaller --distpath=../../../build/cfg_daemon/dist 
#将build目录设置到指定位置
pyinstaller --workpath=../../../build/cfg_daemon/build

02. 添加额外的模块目录(配置,脚本,数据)

#cfg:cfg 前一个cfg是打包时当前目录./cfg 后一个是打包后位于dist目录./_internel/cfg目录
--add-data cfg:cfg 
--add-data ext_ep:ext_ep

注意,最终的./cfg如果与其他模块公用,可以通过设置ln -s的符号连接来实现。 

03.去除特定目录和文件

#去除整个目录
--exclude=trash 
#去除单个文件,注意它们的语法不同。
--exclude-module north_bridge/named_pipe_client.py

#最终的实际打包的文件和配置在:*.spec文件中可以看到:

#下面是.spec中实际包含的文件,数据配置文件:
a = Analysis(
    ['daemon_mqtt_message.py', 'sub/appConfig.py', 'sub/mqtt_message_check.py', 'sub/mqtt_message_reply.py', 'sub/mqtt_message_save.py', 'sub/mysql_con
fig_retrieve.py', 'sub/update_local_json_config_from_mqtt_message.py', 'common/gpLog.py'],
    pathex=[],
    binaries=[],
    datas=[('cfg', 'cfg'), ('ext_ep', 'ext_ep'), ('sub/dumb', 'sub/dumb')],
    hiddenimports=['mysql_config_retrieve'],
    hookspath=[],
    hooksconfig={},
    runtime_hooks=[],
    excludes=[],
    noarchive=False,
    optimize=0,
)

#

04. 对于代码中包含自测模块和处理

pyinstaller 会扫描.py源码中所有的:

if __name__ == "__main__":

    test_gp_calc_envelope()

所以,如果你的源码中,单元测试代码和源码是混在一起的,这个时候就需要避免把这类文件打包进去。

#Step1:pyinstaller打包前不希望打包的模块测试文件改名:
mv math_tools/gp_calc_envelope_test.py math_tools/gp_calc_envelope_test.py.hide
mv math_tools/gp_xjtu_tools_test.py math_tools/gp_xjtu_tools_test.py.hide
mv vibration_calc_test.py vibration_calc_test.py.hide
mv sourth_bridge/gp_xjtu_data_test.py sourth_bridge/gp_xjtu_data_test.py.hide

#Step2:执行pyinstaller
yes | pyinstaller vibration_calc.py math_tools/*.py error_detect/*.py north_bridge/*.py --add-data cfg:cfg --argv-emulation --distpath ../../../../build/py/dist --workpath ../../../../build/py/build --exclude-module vibration_calc_test.py  --exclude-module math_tools/gp_calc_envelope_test.py --exclude-module math_tools/gp_xjtu_tools_test.py --exclude=trash --exclude-module north_bridge/named_pipe_client.py --exclude-module north_bridge/named_pipe_src.py  --exclude-module sourth_bridge/gp_xjtu_data_test.py 

#Step3:不希望打包的文件名字改回
mv math_tools/gp_calc_envelope_test.py.hide math_tools/gp_calc_envelope_test.py
mv math_tools/gp_xjtu_tools_test.py.hide math_tools/gp_xjtu_tools_test.py
mv vibration_calc_test.py.hide vibration_calc_test.py
mv sourth_bridge/gp_xjtu_data_test.py sourth_bridge/gp_xjtu_data_test.py.hide

#Step4:最终二进制发行包的打包:
cd ../../../../build/py/dist/vibration_calc
tar czvf ../../vibration_calc.tar.gz *

05. 只适应调用.py或pyinstaller打包后的文件的自适应处理:

注意execlp的前两个参数都是可执行文件,要重复两遍。

void InvokePythonModule(const char *param)
{
    static int  isInvokePython = -1;
    struct stat buffer;
    const char* python_filename = "./py/vibration_calc.py";
    const char* pyinstaller_filename = "./py/vibration_calc";
    if (stat(python_filename, &buffer) == 0) {
        //printf("文件存在\n");
        isInvokePython = 1;
    }
    else {
        isInvokePython = 0;
    }
    switch (isInvokePython)
    {
    case 0:
        execlp(pyinstaller_filename, pyinstaller_filename, param, NULL);
        break;
    case 1:
        execlp("python3", "python3", python_filename, param, NULL);
        break;
    default:
        printf("py_calc module is missing"); fflush(stdout);
        calcOverlapped->ret = GPCALC_RET_DONE;
        calcOverlapped->errorCode = GPCALC_CALC_MODULE_MISSING;
        exit(0);
        //break;
    }
}

1.案例:python已经启用了多个实例,导致打包时失败

yes | rm -rf dist
yes | pyinstaller daemon_mqtt_message.py sub/*.py common/*.py  --add-data cfg:cfg --add-data ext_ep:ext_ep --hidden-import mysql_config_retrieve
tar czvf daemon_mqtt_message.tar.gz -C ./dist/daemon_mqtt_message --strip-components=1 .
cd temp
tar zxvf ../daemon_mqtt_message.tar.gz

222 INFO: PyInstaller: 4.10
222 INFO: Python: 3.6.8
223 INFO: Platform: Linux-3.10.0-1160.el7.x86_64-x86_64-with-centos-7.9.2009-Core
293 INFO: wrote /home/hxjd/src/src_shake/cfg_daemon/daemon_mqtt_message.spec
296 INFO: UPX is not available.
298 INFO: Extending PYTHONPATH with paths
['/home/hxjd/src/src_shake/cfg_daemon',
 '/home/hxjd/src/src_shake/cfg_daemon/sub',
 '/home/hxjd/src/src_shake/cfg_daemon/sub',
 '/home/hxjd/src/src_shake/cfg_daemon/sub',
 '/home/hxjd/src/src_shake/cfg_daemon/sub',
 '/home/hxjd/src/src_shake/cfg_daemon/sub',
 '/home/hxjd/src/src_shake/cfg_daemon/sub',
 '/home/hxjd/src/src_shake/cfg_daemon/common']
1312 INFO: checking Analysis
1315 INFO: Appending 'datas' from .spec
1316 INFO: checking PYZ
1317 INFO: checking PKG
1317 INFO: Bootloader /usr/local/lib/python3.6/site-packages/PyInstaller/bootloader/Linux-64bit-intel/run
1318 INFO: checking EXE
1318 INFO: checking COLLECT
1318 INFO: Building COLLECT COLLECT-00.toc
1342 INFO: Building COLLECT COLLECT-00.toc completed successfully.
./
./daemon_mqtt_message
./libpython3.6m.so.1.0
./lib-dynload/
./lib-dynload/_struct.cpython-36m-x86_64-linux-gnu.so
./lib-dynload/_opcode.cpython-36m-x86_64-linux-gnu.so

[root@localhost temp]# ./daemon_mqtt_message 
Traceback (most recent call last):
  File "daemon_mqtt_message.py", line 11, in <module>
    from sub import mqtt_message_check
  File "PyInstaller/loader/pyimod03_importers.py", line 495, in exec_module
  File "mqtt_message_check.py", line 16, in <module>
  File "PyInstaller/loader/pyimod03_importers.py", line 495, in exec_module
  File "mysql_config_retrieve.py", line 11, in <module>
ModuleNotFoundError: No module named 'mysql'
[40081] Failed to execute script 'daemon_mqtt_message' due to unhandled exception!

1.1 正确的应对: 

1.1.1 为当前应用程序创建python虚拟执行环境

python3.11 -m venv gp_python_env

1.1.2 激活这个执行环境

source gp_python_env/bin/activate

(gp_python_env) [root@localhost cfg_daemon]#

 1.1.3 之后安装组件和打包都在这个虚拟环境里进行

gp_poython_env/bin/pip install....


 

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值