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 https://www.dll-files.com/geos_c.dll.html
放在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
https://blog.csdn.net/weixin_43218120/article/details/108596405
.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'
)