打包含PaddleOCR的Flask应用为可执行文件时遇USER_SITE为None错误
解决PyInstaller/py2app打包PaddleOCR Flask应用时site.USER_SITE为None的问题
问题情况
用PyInstaller或py2app打包基于PaddleOCR的Flask应用,生成的可执行文件运行时直接报错终止,错误信息如下:
File ".../dist/ocr-app.app/Contents/Resources/lib/python3.9/paddle/fluid/core.py", line 392, in set_paddle_lib_path
lib_dir = os.path.sep.join([site.USER_SITE, 'paddle', 'libs'])
TypeError: sequence item 0: expected str instance, NoneType found
问题根源是打包后的环境里site.USER_SITE的值为None,且测试发现不含Paddle的py2app打包项目也存在这个情况。
环境信息:python3.9、py2app 0.28.4、Flask 2.2.2、paddlepaddle 2.3.2、paddleocr 2.6.0.1
可行解决方案
1. 提前初始化site.USER_SITE
在Flask应用的入口文件最顶部加入以下代码,强制初始化用户站点路径,若初始化失败则手动指定有效路径:
import site import os # 调用getusersitepackages触发USER_SITE初始化 site.getusersitepackages() # 若初始化后仍为None,手动创建并指定临时路径 if not site.USER_SITE: # 可指定打包后应用内的路径或系统临时目录 site.USER_SITE = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_site') os.makedirs(site.USER_SITE, exist_ok=True)
2. 用猴子补丁替换Paddle的路径设置函数
直接修改Paddle内部的set_paddle_lib_path逻辑,绕过对site.USER_SITE的依赖,在应用启动时执行以下代码:
import paddle.fluid.core import os def patched_set_paddle_lib_path(): # 根据打包结构指定Paddle libs的实际路径 lib_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'paddle', 'libs') # 调用底层路径设置函数 paddle.fluid.core._set_paddle_lib_path(lib_dir) # 替换原函数 paddle.fluid.core.set_paddle_lib_path = patched_set_paddle_lib_path
3. 打包时注入PYTHONUSERBASE环境变量
通过环境变量让site模块生成有效USER_SITE,以py2app为例,修改setup.py:
from setuptools import setup import os APP = ['your_flask_app.py'] DATA_FILES = [] OPTIONS = { 'argv_emulation': True, # 设置PYTHONUSERBASE为打包后应用内的目录 'env': { 'PYTHONUSERBASE': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'user_base'), } } setup( app=APP, data_files=DATA_FILES, options={'py2app': OPTIONS}, setup_requires=['py2app'], )
打包前确保创建user_base目录,或让代码自动创建该目录。
内容的提问来源于stack exchange,提问作者Ülephaze
相关产品推荐
相关产品推荐

