Makefile调用Python脚本时urllib.request属性错误求助
urllib.request属性错误的问题 这问题确实挺迷惑的——明明Python版本是3.8.3,直接在命令行跑脚本完全正常,一通过Makefile执行就报AttributeError: module 'urllib' has no attribute 'request',我帮你排查几个最有可能的原因:
1. 本地同名文件干扰了标准库导入
这是最常见的坑:如果你的工作目录下存在名为urllib.py、urllib.pyc或者request.py的文件,Python会优先导入这些本地文件,而不是系统标准库的urllib模块。
验证方法:
在你的Makefile规则里加一行调试命令,查看Python实际导入的urllib路径:
update_stuff: python --version which python python -c "import urllib; print(urllib.__file__)" # 新增这行调试 python stuff.py
执行make update_stuff后,看输出的urllib.__file__路径:
- 如果是类似
/Users/username/anaconda3/lib/python3.8/urllib/__init__.py,说明是标准库模块; - 如果显示的是当前目录下的文件(比如
./urllib.py),那就是问题根源。
解决方法:
把本地的urllib.py/urllib.pyc/request.py这类同名文件重命名或者删除,避免和标准库模块冲突。
2. Makefile的环境变量(PYTHONPATH)异常
有时候Makefile继承的环境变量和你命令行的环境变量不一样,尤其是PYTHONPATH——这个变量会改变Python的模块搜索路径,导致它从非标准位置导入了urllib。
验证方法:
分别在Makefile和命令行里打印PYTHONPATH:
- 在Makefile的规则里加
echo $PYTHONPATH; - 在命令行直接执行
echo $PYTHONPATH。
对比两者的输出,如果Makefile里的PYTHONPATH多了奇怪的路径,或者和命令行不一致,那就是问题所在。
解决方法:
在Makefile的规则开头重置或者设置正确的PYTHONPATH,比如:
update_stuff: export PYTHONPATH="" # 清空PYTHONPATH,让Python默认搜索标准库 python --version which python python stuff.py
或者直接把命令行里的PYTHONPATH值复制到Makefile中。
3. 强制使用Python绝对路径
虽然which python显示的是Anaconda的Python,但有时候Makefile的PATH环境变量可能和命令行不同,导致实际调用的Python版本有差异(比如系统默认的Python2)。
解决方法:
把Makefile里的python换成你Anaconda Python的绝对路径:
update_stuff: /Users/username/anaconda3/bin/python --version /Users/username/anaconda3/bin/python stuff.py
这样可以彻底避免路径带来的版本混淆问题。
4. 快速检查脚本内的导入逻辑
虽然你直接跑脚本正常,但还是可以快速确认:
- 脚本里有没有修改
sys.path的代码?比如sys.path.insert(0, "./")这类可能导致优先导入本地模块的操作; - 有没有错误的导入语句,比如
from urllib import *之后又尝试调用urllib.request?不过这种情况直接跑脚本也会报错,可能性较低。
按照上面的步骤排查,应该就能定位到问题啦!
内容的提问来源于stack exchange,提问作者John Smith

