前言

由于项目需求,需要在 PHP 脚本中调用一个 Python 算法。之前和 Lll 一起做毕设的时候也曾使用 PHP 脚本调用过 Python 编写的协同过滤算法,当时没有出现什么大的问题。但在本次开发过程中,由于 Python 脚本中 cv2 包的引入导致了 PHP 调用 Python 脚本时报错,无法取得正确的运行结果。这次错误排查一波三折,排查的过程也暴露了我本人的一些疏漏,特此记录,以警醒自身。

正文

1 错误描述

在 PHP 文件中使用 shell_exec() 函数调用目标 Python 脚本,该 Python 脚本的运行结果会保存一张图片在指定文件夹中,但运行 PHP 脚本后发现该 Python 脚本没有被成功调用,无事发生。

但在命令行中调用 PHP 脚本发现 Python 脚本可以被成功调用,这就很奇怪了,这说明 PHP 程序没有任何问题。

2 解决过程

在解决的过程中尝试过很多方法,比如路径是否都写成绝对路径了、Python 的环境变量是否正确之类……但其实这些都是盲目的抓瞎,查找问题还是要看错误提示

这就是我踩的第一个坑,因为我直接使用 PHP 中的 shell_exec() 方法调用 Python 脚本失败后并没有在 Web 页面显示任何错误信息,而我在没有查看错误提示的情况下就开始盲目地排查错误的原因,导致浪费了很多时间。

输出错误信息的方法就是在所调用的脚本后加入 2>&1

2>&1 涉及到 Linux 的三种标准输入输出,如下:

  • STDIN:标准输入,编号0
  • STDOUT:标准输出,编号1
  • STDERR:标准错误输出,编号2

因此,2>&1 的含义就是把错误信息重定向到输出

得到错误信息后问题就好解决了,我的错误提示是 cv2 模块不存在,因此先使用 sys.path.append 导入 cv2 模块所在路径。之后又报错 numpy 版本有问题,和 Python 版本不兼容。

google 了一下,是系统里有两个 numpy 模块,一个是系统 Python 自带的,一个是我用 Homebrew 手动安装的。为了统一版本,我用 Homebrew 重新安装了 Python,并弃用系统自带的 Python。问题得到解决。

总结

当时焦头烂额地找了一天的 Bug,现在想想也没有什么大的问题,关键在于我本身查找错误的方式不对,在 Python 环境的安装上也太过粗心。记录在此,引以为戒。