absa_annotation虚拟环境导入secure_filename报ImportError咨询
触发本次报错的和你自己编写的from werkzeug.utils import secure_filename代码无关——从错误栈可以看到,程序执行到第4行导入flask_uploads模块时就已经抛出异常,根本没执行到你写的werkzeug导入语句。
问题本质是依赖版本不匹配:
高版本Werkzeug(2.0及以上)已经移除了顶层模块对secure_filename、FileStorage的直接导出,这两个功能现在分别归属在werkzeug.utils、werkzeug.datastructures子模块下。但你当前absa_annotation虚拟环境里安装的flask_uploads是停止维护的老版本,还在按旧的导入规则从werkzeug顶层直接导入这两个方法,因此触发导入错误。
这也能解释为什么你的代码在基础虚拟环境中可以正常运行:那个环境里安装的是Werkzeug 1.x的旧版本,顶层模块还保留了兼容导出,能匹配老版flask_uploads的导入逻辑。
可选解决方案
快速临时处理:降级当前虚拟环境的Werkzeug到兼容版本
直接在已激活的absa_annotation虚拟环境中执行安装命令:pip install werkzeug==1.0.1
这个版本的Werkzeug保留了旧的顶层导出逻辑,可直接匹配老版flask_uploads的导入要求,安装完成后即可正常启动程序。长期稳妥方案:替换停止维护的flask_uploads包
原flask_uploads项目已多年未更新适配新版本依赖,更推荐使用适配高版本Werkzeug的可维护替代分支:- 卸载旧的不兼容包:
pip uninstall flask-uploads - 安装兼容替代包:
pip install flask-reuploaded - 修改代码中的导入语句,将原来的
from flask_uploads import UploadSet,configure_uploads,IMAGES,DATA,ALL
替换为from flask_reuploaded import UploadSet,configure_uploads,IMAGES,DATA,ALL
- 卸载旧的不兼容包:
不推荐的临时补丁方案
如果暂时不想调整现有依赖版本,可以在所有导入语句的最开头加上兼容补丁,手动把需要的方法挂载到werkzeug顶层模块,绕开老包的导入问题:import werkzeug from werkzeug.utils import secure_filename from werkzeug.datastructures import FileStorage # 给werkzeug顶层补充旧版兼容导出 werkzeug.secure_filename = secure_filename werkzeug.FileStorage = FileStorage这种方式仅属于临时兼容处理,后续如果遇到其他同样依赖旧版werkzeug导入逻辑的第三方包,仍需要逐个打补丁,长期维护成本较高。
内容的提问来源于stack exchange,提问作者louis lau

