crontab运行Python脚本报No module named requests终端运行正常
问题根因
该故障和Google邮件发送配置修改无关联,属于时间点巧合。核心原因是执行环境的Python解释器版本不匹配:
- 你通过
pip3将requests安装到了Python 3.6的用户级site-packages目录下 - 你写的bash启动脚本中使用
python命令调用脚本,在crontab的非交互式shell环境、以及未加载用户alias配置的bash场景下,python默认指向Python 2.x版本,Python 2无法识别Python 3路径下安装的第三方库,因此抛出导入错误 - 终端直接执行脚本能正常运行,是因为你的终端shell加载了自定义配置(比如将
pythonalias到python3),和crontab/裸bash执行的环境不一致。
快速排查验证
执行以下命令即可确认问题:
- 分别执行
python --version、python3 --version,可以看到两个命令对应的解释器版本差异 - 执行
python -m pip list | grep requests,会返回空结果,证明默认python环境下未安装requests - 在测试脚本中加入
import sys; print(sys.version, sys.path),执行bash脚本时会打印出当前调用的是Python 2版本,且搜索路径中不包含Python 3.6的用户库目录。
解决方案
优先选第一种方案,稳定性最高,不受环境变量变动影响:
- 使用Python3绝对路径调用脚本
先在终端执行which python3获取Python3解释器的绝对路径(通常为/usr/bin/python3),修改test_request.sh的启动行:
注:你之前写的重定向顺序#!/bin/bash echo "test_request.sh called: $(date)" HOME=/home/user/ cd /home/user/Documents/bjg_code/ # 替换为你实际查到的python3绝对路径,删掉之前硬写的PYTHONPATH配置 /usr/bin/python3 ./test_request.py >/dev/null 2>&12>&1 1>/dev/null是错误的,会导致错误日志无法正常丢弃,正确的全输出重定向顺序是先定向stdout,再定向stderr到stdout。 - crontab全局配置PATH(适合多任务场景)
如果crontab里有大量Python3任务,可以直接在crontab文件最顶部添加PATH配置,让所有任务都能优先找到Python3:PATH=/home/user/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # 下方写你的定时任务即可,调用时直接用python3命令 * * * * * /bin/bash /home/user/Documents/bjg_code/test_request.sh
避坑提示
- 不要在crontab任务中依赖shell alias、用户级shell配置文件(
.bashrc/.zshrc)里的自定义设置,crontab执行的是非交互式、非登录shell,不会加载这些配置,所有命令尽量写绝对路径,是规避crontab环境问题最通用的方案。 - 不要硬编码
PYTHONPATH指向单版本的site-packages目录,这种写法会导致解释器无法自动搜索其他依赖路径,容易出现其他第三方库导入失败的问题,用对应版本的解释器自动搜索默认路径可靠性更高。
内容的提问来源于stack exchange,提问作者Brian Graham
相关产品推荐
相关产品推荐

