PyInstaller打包问题
- 1. Failed to execute script pyi_rth_win32compenpy
- 2. OSError: could not find or load spatialindex_c-64.dll
- 3. ModuleNotFoundError:No module named 'fiona._shim' / No module named 'fiona.schema'
- 4. StopIteration问题
- 5. AttributeRrror: partially initialized module 'fiona' has no attribute '_loading'(most likely due to a circular import)
- 6. 打包后出现 ModuleNotFoundError: no module named 'rasterio._shim',以及其他rasterio相关属性
- 7. Fatal error: PyInstaller does not include a pre-compiled bootloader for your platform
- 8. A RecursionError (maximum recursion depth exceeded) occurred.
- 9.1 Error loading Python DLL 'C:\Users\Administrator\AppData\Local\Temp\_MEI192042\python36.dll'
- 9.2 'C:\Users\Administrator\AppData\Local\Temp\_MEI156882\VCRUNTIME140.DLL'没有被指定再Windows上运行,或包含其他错误。
- 10. FileNotFoundError
- 11. 打包界面在别的电脑运行时出现“程序启动失败,因为计算机中丢失api-ms-win-core-path|1-1-0.dll”.
- 12. 终端激活虚拟环境后运行python,出现无法启动python,因为计算机中丢失api-ms-win-core-path|1-1-0.dll。
- 13.1 ERROR: proj_create_from_database: Cannot find proj.db
- 13.2 ERROR: Translating source or target SRS failed:
- 14. pyinstaller打包提示PermissionError: [Errno 13] Permission denied....\\ucrtbase.dll权限问题
- 15. no module named 'osgeo._gdal'问题
- 16. ValueError: Module file XXX.py is missing
- 17. no module named 'numpy.distutils'
- 18.1. PyInstaller: ImportError: cannot import name 'ccompiler' from partially initialized module 'numpy.distutils'
- 18.2. PyInstaller: ImportError: cannot import name 'log' from partially initialized module 'numpy.distutils'
- 附:.spec样例:
当进行遥感数据处理时,python代码会用到GDAL、geopandsa、fiona、rasterio等系列库包,代码运行正常,想生成exe交给第三方使用时,需要进行程序打包。然而在利用pyinstaller进行打包时,自己遇到了一系列问题,花费很久的时间才一一解决,现将过程中所遇到的问题及解决方案进行汇总记录,希望帮到更多的人~~
1. Failed to execute script pyi_rth_win32compenpy
通过安装最新版本PyInstaller解决,控制台输入以下命令:
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.zip
2. OSError: could not find or load spatialindex_c-64.dll
通过编辑.spec文件解决
添加 from PyInstaller.utils.hooks import collect_dynamic_libs
设置 binaries=collect_dynamic_libs(“rtree”)
3. ModuleNotFoundError:No module named ‘fiona._shim’ / No module named ‘fiona.schema’
编辑.spec文件
a = Analysis 上方添加如下代码:
hidden_imports = [
‘fiona._shim’,
‘fiona.schema’,
]
修改:hiddenimports=hidden_imports
4. StopIteration问题
找到geopandas库文件下的__init__.py
,将import geopandas.datasets
这句注释掉
5. AttributeRrror: partially initialized module ‘fiona’ has no attribute ‘_loading’(most likely due to a circular import)
_loading 循环导入原因
解决方案:打包的py脚本在最开始一次导入fiona、rasterio、geopandas模块。
6. 打包后出现 ModuleNotFoundError: no module named ‘rasterio._shim’,以及其他rasterio相关属性
解决方案:将rasterio下所有属性添加至hidden_imports中,代码如下:
import glob, os
rasterio_imports_paths1 = glob.glob(r'D:\ProgramData\conda\envs\ecological_system\Lib\site-packages\rasterio\*.py')
rasterio_imports_paths2 = glob.glob(r'D:\ProgramData\conda\envs\ecological_system\Lib\site-packages\rasterio\*.pyd')
hidden_imports = [
'fiona._shim',
'fiona.schema',
'rasterio._shim',
]
for item in rasterio_imports_paths1:
current_module_filename = os.path.split(item)[-1]
current_module_filename = 'rasterio.'+current_module_filename.replace('.py', '')
hidden_imports.append(current_module_filename)
for item in rasterio_imports_paths2:
current_module_filename = os.path.split(item)[-1]
current_module_filename = 'rasterio.'+current_module_filename.replace('.pyd', '')
current_module_filename = current_module_filename.split('.')[0] + '.' + current_module_filename.split('.')[1]
hidden_imports.append(current_module_filename)
# 修改hiddenimports
hiddenimports=hidden_imports
7. Fatal error: PyInstaller does not include a pre-compiled bootloader for your platform
之前安装的是pyinstaller5.0版本,且是通过源码进行编译安装的。
解决方案:卸载该版本,在Python extension package网页下载pyinstaller4.3版本及pyinstaller-hooks-contrib两个 whl文件,使用pip进行离线安装,将 .spec 中 hooksconfig={}, 行删除。
8. A RecursionError (maximum recursion depth exceeded) occurred.
在.spec文件开始添加下行代码:
import sys
sys.setrecursionlimit(sys.getrecursionlimit() * 5)
9.1 Error loading Python DLL ‘C:\Users\Administrator\AppData\Local\Temp_MEI192042\python36.dll’
9.2 'C:\Users\Administrator\AppData\Local\Temp_MEI156882\VCRUNTIME140.DLL’没有被指定再Windows上运行,或包含其他错误。
问题9.1 是界面提示,问题9.2 是控制台提示
将.spec文件中的upx=True,修改为upx=False, 得以解决。
10. FileNotFoundError
打包的exe位于dist文件夹中,将配置文件也放在该文件夹下即可。
11. 打包界面在别的电脑运行时出现“程序启动失败,因为计算机中丢失api-ms-win-core-path|1-1-0.dll”.
12. 终端激活虚拟环境后运行python,出现无法启动python,因为计算机中丢失api-ms-win-core-path|1-1-0.dll。
问题11与12的解决方法:将文件“api-ms-win-core-path-l1-1-0.dll”放置到电脑c:\Windows\System32文件夹中,重启电脑,重启界面或虚拟环境。
13.1 ERROR: proj_create_from_database: Cannot find proj.db
13.2 ERROR: Translating source or target SRS failed:
问题原因:缺少proj.db的环境变量
解决方案:1. 存在该程序python环境或conda虚拟环境时:将环境内的 ‘’**\share\proj" 路径添加至系统变量中,新建变量名为‘PROJ_LIB’,变量值为该路径,路径内包含 proj.db文件。
- 电脑上没有python环境时,打包前将proj.db 放置在打包路径下,创建‘hook.py’(代码如下:名称可以自定义),修改runtime_hooks参数,使runtime_hooks = [‘hook.py’],打包完成后将proj.db当作配置文件,放置在与exe同路径下即可。
import os
import sys
os.environ['PROJ_LIB'] = os.path.dirname(sys.argv[0])
14. pyinstaller打包提示PermissionError: [Errno 13] Permission denied…\ucrtbase.dll权限问题
解决方案:关闭360等杀毒软件后重新打包
15. no module named 'osgeo._gdal’问题
目前‘eco’python38虚拟环境内使用的GDAL是3.3.2的版本,查验后发现其____init____.py运行失败,将39环境内3.2.3版本____init____.py进行替换后可以运行。
主要问题应该是在环境变量上。
16. ValueError: Module file XXX.py is missing
这个问题出现在将py文件编译为pyd文件后,因为pyd的优先级高于py,打包时pyinstaller会自动选择编译后的pyd文件而非py文件
解决方案:不能将入口的py文件也生成pyd,否则pyinstaller打包时会提示以上错误
17. no module named ‘numpy.distutils’
解决方案1:在打包py脚本中 添加 import numpy.distutils,但是后续可能会出现问题19,问题20之类的新的问题;
解决方案2:找到运行环境下 rasterstats/main.py文件,将第八行注掉,但是这种方法如果代码里面用到了第八行的相关函数,程序运行时就会出现错误
18.1. PyInstaller: ImportError: cannot import name ‘ccompiler’ from partially initialized module ‘numpy.distutils’
18.2. PyInstaller: ImportError: cannot import name ‘log’ from partially initialized module ‘numpy.distutils’
解决方案:在打包py脚本中 添加 import numpy.distutils.ccompiler 以及import numpy.distutils.log
附:.spec样例:
# -*- mode: python ; coding: utf-8 -*-
"""
date:2021/7/8
author:甲戌_Tr
email: liu_xxxi@163.com
"""
block_cipher = None
import glob, os
from PyInstaller.utils.hooks import collect_dynamic_libs
rasterio_imports_paths1 = glob.glob(r'D:\ProgramData\conda\envs\ecological_system\Lib\site-packages\rasterio\*.py')
rasterio_imports_paths2 = glob.glob(r'D:\ProgramData\conda\envs\ecological_system\Lib\site-packages\rasterio\*.pyd')
hidden_imports = [
'fiona._shim',
'fiona.schema',
'rasterio._shim',
]
for item in rasterio_imports_paths1:
current_module_filename = os.path.split(item)[-1]
current_module_filename = 'rasterio.'+current_module_filename.replace('.py', '')
hidden_imports.append(current_module_filename)
for item in rasterio_imports_paths2:
current_module_filename = os.path.split(item)[-1]
current_module_filename = 'rasterio.'+current_module_filename.replace('.pyd', '')
current_module_filename = current_module_filename.split('.')[0] + '.' + current_module_filename.split('.')[1]
hidden_imports.append(current_module_filename)
a = Analysis(['E:\\test.py'],
pathex=['E:\\python_code'],
binaries=collect_dynamic_libs("rtree"),
datas=[],
hiddenimports=hidden_imports,
hookspath=[],
runtime_hooks=[], # 是否需要修改详见问题13
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='demo',
debug=True,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False )