pyinstaller打包报错以及解决

#使用方法

 -h,--help 查看该模块的帮助信息
 -F,-onefile 产生单个的可执行文件
 -D,--onedir 产生一个目录(包含多个文件)作为可执行程序
 -a,--ascii 不包含 Unicode 字符集支持
 -d,--debug 产生 debug 版本的可执行文件
 -w,--windowed,--noconsolc 指定程序运行时不显示命令行窗口(仅对 Windows 有效)
 -c,--nowindowed,--console 指定使用命令行窗口运行程序(仅对 Windows 有效)
 -o DIR,--out=DIR 指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件
 -p DIR,--path=DIR 设置 Python 导入模块的路径(和设置 PYTHONPATH 环境变量的作用相似)。也可使用路径分隔符(Windows 使用分号,Linux 使用冒号)来分隔多个路径
 -n NAME,--name=NAME 指定项目(产生的 spec)名字。如果省略该选项,那么第一个脚本的主文件名将作为 spec 的名字

打包命令

 pyinstaller -F thired.py
 pyinstaller -F -i ajai4-i7gr6-001.ico db.py
 pyinstaller -F -i jykj.ico -w acx-14.spec 没有命令行
 pyinstaller -F -w -i "res/jykj.ico" --key "chenziqing-data" text.py --add-data="res/*.*;./res"

pyinstaller打包报错

1、Error: geos_c.dll

 Error: geos_c.dll not found, required by hook-shapely.py.
 Please check your installation or provide a pull request to PyInstaller to update hook-shapely.py

去下载geos_c.dll geos_c.dll free download | DLL‑files.com 放在C:\Windows\System32 下

2、RecursionError: maximum recursion depth exceeded

 import sys
 sys.setrecursionlimit(5000)

3、IMPORTERROR: NO MODULE NAMED ‘MLARRAY‘解决方案 mlarray

 https://www.freesion.com/article/46391125160/
 pyinstaller test.py --additional-hooks-dir=hooks
 pyinstaller -F -i jykj.ico -w asphalt-计算PCISCI-5.spec --additional-hooks-dir=hooks
 ​
 会遇到的打包问题
 https://www.cnblogs.com/alex-13/p/12849264.html
 打包资源维问题
 https://blog.csdn.net/kobeyu652453/article/details/108732747
 ​
 ​
 ​

4、WARNING: file already exists but should not: torch_C.cp36-win_amd64.pyd

WARNING: file already exists but should not: C:\Users\workAI\AppData\Local\Temp\_MEI132522\torch\_C_黄小黄i的博客-CSDN博客

 ​
 .spec
 添加下面行
 for d in a.datas:
     if '_C.cp36-win_amd64.pyd' in d[0]:
         a.datas.remove(d)
         break
 ​
 ​
 ​
 ​
 a = Analysis(['MyTcpServer.py'],
              pathex=['G:\\yolo'],
              binaries=[],
              datas=[],
              hiddenimports=[],
              hookspath=[],
              runtime_hooks=[],
              excludes=[],
              win_no_prefer_redirects=False,
              win_private_assemblies=False,
              cipher=block_cipher,
              noarchive=False)
 for d in a.datas:
     if '_C.cp37-win_amd64.pyd' in d[0]:
         a.datas.remove(d)
         break
 ​
 ​
 ​

5、ctypes 找不到依赖pypiwin32 或pywin32-ctypes

 ​
 # ctypes 找不到依赖pypiwin32 或pywin32-ctypes
 # Traceback (most recent call last):
 #   File "lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py", line 151, in __init__
 #   File "ctypes\__init__.py", line 348, in __init__
 # OSError: [WinError 126] 找不到指定的模块。
 """
 在python安装路径下找到Lib/site-packages/Pyinstaller目录下有个compat.py文件定位到212行
 ​
 源码如下:
 ​
 复制代码
 if is_win:
     try:
         from win32ctypes.pywin32 import pywintypes  # noqa: F401
         from win32ctypes.pywin32 import win32api
     except ImportError:
         xxxx
         xxxx
 点击并拖拽以移动
 复制代码
 做如下修改:将两个from改为import
 ​
 复制代码
 if is_win:
     try:
         # from win32ctypes.pywin32 import pywintypes  # noqa: F401
         # from win32ctypes.pywin32 import win32api
         import pywintypes
         import win32api
     except ImportError:
         xxxx
         xxxx
 复制代码
  

6、PyInstaller解决 ImportError: cannot import name ‘PackagePath‘ from ‘importlib_metadata‘

 '''
 PyInstaller解决 ImportError: cannot import name ‘PackagePath‘ from ‘importlib_metadata‘
 '''
 # cannot import name ‘PackagePath’ from ‘importlib_metadata’: Python 3.7
 # 问题和解决方案:
 # importlib_metadata版本太老了,升级一下
 # pip install importlib-metadata --upgrade
 ​
 '''
 第一步:卸载,重装(在anaconda prompt里)或者虚拟环境下
 pip uninstall matplotlib
 ​
 pip install matplotlib==3.1.1
 ​
 第二步:打包
 pyinstaller -F XXX.py
 ​
 第三步:修改spec文件
 原hiddenimports=[],
 ​
 修改后
 ​
 hiddenimports=[‘matplotlib’],
 '''
 ​

7、Path in environment MATPLOTLIBDATA not a directory

 ​
 # Path in environment MATPLOTLIBDATA not a directory
 """
 在spec文件中的excludes行加上excludes=['matplotlib'],
 hiddenimports=['numpy.random.common'],然后pyinstaller xx.spec重新封装一遍。
 ​

8、Mac Osx/Windos 使用pyinstalle 打包后图标不生效

 ​
 Mac Osx/Windos 使用pyinstalle 打包后图标不生效
 我尝试了很久才发现,Mac下图标文件为icns格式Win为ico
 ​
 # Mac 使用pyinstalle打包配置图标
 pyinstaller test.py --noconsole --icon=logo.icns
 # Windos 使用pyinstalle打包配置图标
 pyinstaller test.py --noconsole --icon=logo.ico
 ​

.spec用法

 # -*- mode: python ; coding: utf-8 -*-
 block_cipher = pyi_crypto.PyiBlockCipher(key='chenziqing-data')
 a = Analysis(['应变计-裂缝计-倾角计-数据接入.py'],
              pathex=[],
              binaries=[],
              datas=[('res/*.*', './res')],
              hiddenimports=[],
              hookspath=[],
              hooksconfig={},
              runtime_hooks=[],
              excludes=[],
              win_no_prefer_redirects=False,
              win_private_assemblies=False,
              cipher=block_cipher,
              noarchive=False)
 pyz = PYZ(a.pure, a.zipped_data,
              cipher=block_cipher)
 exe = EXE(pyz,
           a.scripts,
           a.binaries,
           a.zipfiles,
           a.datas,  
           [],
           name='应变计-裂缝计-倾角计-数据接入',
           debug=False,
           bootloader_ignore_signals=False,
           strip=False,
           upx=True,
           upx_exclude=[],
           runtime_tmpdir=None,
           console=False,
           disable_windowed_traceback=False,
           target_arch=None,
           codesign_identity=None,
           entitlements_file=None , 
           icon='res\\jykj.ico')

block_cipher

 上面还有个变量block_cipher,主要是防止exe被反编译。
 block_cipher = pyi_crypto.PyiBlockCipher(key='chenziqing-data')

Analysis

datas用法

 # 第一个写文件路径,第二个写位置 如 . /res/ data 等
 datas = [('res/三极子偕行楷.ttf', 'res'), ('res/851手写杂书体.ttf', 'res'), ('res/千图笔锋手写体.ttf', 'res'), ('res/千图纤墨体.ttf', 'res'),
          ('res/王强手写体.ttf', 'res'), ]
          
 如果在exe中进行引用的话需要使用方法如下
 ttf = processPath("res/三极子偕行楷.ttf") 对ttf进行引用
     
 #https://blog.csdn.net/u012917013/article/details/125860885
 def processPath(path):
     '''
     针对pyInstaller打包程序而设计。这是官方给出的方案。
     在pyInstaller打包时,会给sys设置属性frozen,
     并且会将打包程序的绝对路径存储在sys._MEIPASS。
     所以当不打包程序时,不需要使用该方案拼接路径
     :param path: 相对于根目录的路径
     :return: 拼接好的路径
     '''
     # if getattr(sys, 'frozen', False):  # 判断是否存在属性frozen,以此判断是打包的程序还是源代码。false为默认值,即没有frozen属性时返回false
     #     base_path = sys._MEIPASS  # 该属性也是打包程序才会有,源代码尝试获取该属性会报错
     # else:
     #     base_path = os.path.abspath(".")  # 当源代码运行时使用该路径
     # return os.path.join(base_path, path)
     """ 获得资源的绝对路径 """
     try:
         # PyInstaller 创建临时文件夹时会将路径存入 sys._MEIPASS
         base_path = sys._MEIPASS
     except Exception:
         # 不是 exe 执行环境,未找到 sys._MEIPASS,使用当前路径
         base_path = os.path.abspath(".")
     return os.path.join(base_path, path)

PYZ

 pyz = PYZ(a.pure, a.zipped_data,
              cipher=block_cipher)

exe

 exe = EXE(pyz,
           a.scripts,
           a.binaries,
           a.zipfiles,
           a.datas,  
           [],
           name='应变计-裂缝计-倾角计-数据接入',
           debug=False,
           bootloader_ignore_signals=False,
           strip=False,
           upx=True,
           upx_exclude=[],
           runtime_tmpdir=None,
           console=False,
           disable_windowed_traceback=False,
           target_arch=None,
           codesign_identity=None,
           entitlements_file=None , 
           icon='res\\jykj.ico'
           )

你可能感兴趣的:(python)