PHP调用Python3脚本失败求助:numpy模块AttributeError报错
问题:PHP调用Python聚类脚本在Apache环境下失败,命令行正常
背景
本地PHP5环境中,PHP脚本可正常调用Python3执行聚类分析:小数据通过shell_exec传递参数,大数据通过exec让Python读取JSON文件。但迁移到Apache2+PHP7.4.3服务器后,PHP无法执行带数据处理依赖的Python脚本——仅做JSON读写的脚本能正常运行,涉及scipy、pandas的脚本直接报错,但服务器命令行执行该Python脚本完全正常。
已尝试的操作:
- 使用Python3完整路径调用脚本
- 在Python脚本顶部添加shebang声明
- 给相关文件设置读写权限
错误堆栈
Traceback (most recent call last): File "/var/www/testsite/py/hclust_esc.py", line 4, in <module> import scipy.cluster.hierarchy as sch File "/usr/lib/python3/dist-packages/scipy/cluster/__init__.py", line 27, in <module> from . import vq, hierarchy File "/usr/lib/python3/dist-packages/scipy/cluster/vq.py", line 74, in <module> from scipy.spatial.distance import cdist File "/usr/lib/python3/dist-packages/scipy/spatial/__init__.py", line 99, in <module> from .kdtree import * File "/usr/lib/python3/dist-packages/scipy/spatial/kdtree.py", line 8, in <module> import scipy.sparse File "/usr/lib/python3/dist-packages/scipy/sparse/__init__.py", line 229, in <module> from .base import * File "/usr/lib/python3/dist-packages/scipy/sparse/base.py", line 8, in <module> from .sputils import (isdense, isscalarlike, isintlike, File "/usr/lib/python3/dist-packages/scipy/sparse/sputils.py", line 16, in <module> supported_dtypes = [np.typeDict[x] for x in supported_dtypes] File "/usr/lib/python3/dist-packages/scipy/sparse/sputils.py", line 16, in <listcomp> supported_dtypes = [np.typeDict[x] for x in supported_dtypes] File "/usr/local/lib/python3.8/dist-packages/numpy/__init__.py", line 320, in __getattr__ raise AttributeError("module {!r} has no attribute " AttributeError: module 'numpy' has no attribute 'typeDict'
服务器安装的numpy版本为1.21.0,命令行执行无此错误。
解决方案
1. 统一Python环境
从错误路径可看出:PHP调用时加载的是/usr/local/lib/python3.8/dist-packages/numpy,而命令行使用的是另一个环境(比如系统自带的/usr/lib/python3/dist-packages),两个环境的依赖版本不匹配导致报错。
解决方法:
- 找到命令行使用的Python完整路径:执行
which python3,得到路径如/usr/bin/python3 - 在PHP的
exec或shell_exec中直接用该完整路径调用脚本:exec('/usr/bin/python3 /var/www/testsite/py/hclust_esc.py'); - 更稳妥的方式是创建与命令行环境一致的虚拟环境,使用虚拟环境的Python路径调用脚本。
2. 修复依赖版本兼容性
np.typeDict在numpy 1.20之后被移除,替换为np.dtypeDict,若PHP调用环境中的scipy版本过旧,就会出现该错误。
解决方法:
- 找到PHP调用的Python对应的pip路径,比如
/usr/local/bin/pip3 - 升级scipy到兼容numpy 1.21.0的版本:
/usr/local/bin/pip3 install --upgrade scipy
3. 配置环境变量
Apache用户(通常为www-data)的环境变量与登录用户不同,可能导致依赖包路径无法识别。可在调用时指定PYTHONPATH:
exec('export PYTHONPATH="/usr/lib/python3/dist-packages" && /usr/bin/python3 /var/www/testsite/py/hclust_esc.py');
内容的提问来源于stack exchange,提问作者schustischuster
相关产品推荐
相关产品推荐

