Python教程

Pyinstaller打包python程序到.exe种种坑

本文主要是介绍Pyinstaller打包python程序到.exe种种坑,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

背景

用python写了一个线性规划求解问题的小程序。程序用到了numpy、pandas、scipy和pyqt5。为了在没有python环境的电脑下运行程序,用pyinstaller将写好的程序打包成.exe可执行文件。

打包过程遇到了多种问题,包括

  • 提示缺少dll文件
  • 打包好的程序不报错闪退或卡死
  • pip无法安装到创建的虚拟环境下
  • pyinstaller打包好的代码缺少依赖文件
  • pyinstaller打包好的代码过大
  • bat文件进行打包过程的批量处理

开发环境

```bash
Anaconda
	python 3.8.11
	numpy 1.20.3
	scipy 1.6.2
	pandas 1.3.2
	PyQt 5.9.2
```

Debug

  • 运行打包好的程序卡死或者闪退
    • 问题
      在开发环境的电脑上打包好后,打开cmd执行main.exe,提示错误缺少mkl_intel_thread.1.dll,从Anaconda目录下搜索该文件拷贝到main.exe同目录下,再次执行main.exe不再报错

      本以为问题已经顺利解决,但是把打包好的文件拷贝到一台没有python环境的电脑上打开后不报错闪退,或是用cmd执行main.exe则出现“程序无响应”但窗口仍然没有任何错误提示信息。对代码逐行排查后发现是import numpy as np语句导致的程序退出。结合上述遇到的mkl_intel_thread.1.dll导致问题,怀疑是将dll文件拷贝到文件夹下后无法被正确执行。

    • 解决
      查找资料发现conda install numpy会自动下载带mkl加速版本的numpy,而pip install numpy下载的则不带。因此考虑numpy的版本。
      首先创建一个新的conda虚拟环境:

      conda create -n pyqt5
      

      切换到创建的虚拟环境

      conda activate pyqt5
      

      在环境中安装所需库

      conda install pyinstaller
      conda install pyqt
      

      pip安装剩余库,这里又存在一个问题。虽然切换到了虚拟环境pyqt5,但是使用pip install仍然会安装到原始环境下。一个简单解决办法是cdD:\Anaconda3\envs\pyqt5目录下,再执行pip install

      pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy
      pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pandas
      pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scipy
      

      最后确认你的cmd处于pyqt5虚拟环境下,执行

      pyinstaller -D -w --distpath .\exe\dist --workpath .\exe\build --clean main.py --icon=.\icon\exeicon.ico  --hidden-import scipy.spatial.transform._rotation_groups
      

      -D指明打包文件用多文件的方式保存,这里也是一个坑,如果用-F单文件存储的话很容易出现缺少依赖文件等问题。-D的兼容性更好。
      -w指明运行文件隐藏终端显示。
      这种方式打包好的程序已经无需mkl文件的依赖支持,将其拷贝到无python环境的电脑下顺利运行。

  • pyinstaller打包好的代码过大
    一开始使用单文件模式保存程序,结果发现打包好的程序越来越大,后来发现在执行打包命令之前彻底删除上一次打包的中间和最终文件可解决这个问题。
    使用多文件模式没有此问题。
  • bat文件进行打包过程的批量处理
    我的程序需要用一些json文件进行数据存储,每次打包好都要手动将这些文件复制到目录下很麻烦,因此写了一个.bat文件对打包过程进行批处理。
    @echo off
    call conda activate pyqt5
    call pyinstaller -D -w --distpath .\exe\dist --workpath .\exe\build --clean main.py --icon=.\icon\exeicon.ico  --hidden-import scipy.spatial.transform._rotation_groups
    call echo d | xcopy /S /Y "./json" "./exe/dist/main/json"
    call echo d | xcopy /S /Y "./icon" "./exe/dist/main/icon"
    
    双击.bat文件可以实现自动切换虚拟环境、打包程序、复制文件夹到打包目录下
这篇关于Pyinstaller打包python程序到.exe种种坑的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!