Poetry优先从全局PYTHONPATH而非自身管理的虚拟环境查找包的问题咨询
嘿,我来帮你拆解这个问题——这其实是Python模块查找机制和环境变量优先级共同作用的结果,咱们一步步理清楚:
为什么会出现这个问题?
Python的模块查找顺序是有明确规则的:它会先从PYTHONPATH环境变量指定的路径里找模块,然后才会去当前虚拟环境的site-packages目录,最后才是标准库路径。
Poetry虽然会创建独立的虚拟环境,但它并没有自动覆盖全局的PYTHONPATH变量——当你用poetry run执行脚本时,系统的环境变量(包括PYTHONPATH)会被继承到虚拟环境的运行上下文里。所以Python会先去你指定的3.8全局site-packages里找numpy,而那个版本和3.12不兼容,自然就报错了。至于keyboard能正常导入,纯粹是因为3.8全局环境里没装它,Python才会退而求其次去虚拟环境里找。
怎么解决这个问题?
这里有几个靠谱的方案,你可以根据自己的需求选:
临时清空PYTHONPATH再运行:
不用删系统变量,每次运行前在终端里临时覆盖这个变量就行,比如在PowerShell里:$env:PYTHONPATH="" ; poetry run .\test.py这样只会在当前终端会话里生效,完全不影响其他依赖
PYTHONPATH的程序。让Poetry自动屏蔽全局PYTHONPATH:
你可以在项目的pyproject.toml里配置脚本,或者直接在运行时指定环境变量覆盖:poetry run env PYTHONPATH="" python test.py这种方式相当于给当前Poetry运行会话单独重置
PYTHONPATH,不会影响系统全局设置。给需要PYTHONPATH的程序单独配置:
既然那个Python 3.8的插件需要PYTHONPATH,没必要把它设成系统全局变量——可以只在启动那个软件的快捷方式里添加环境变量:右键快捷方式→属性→快捷方式→目标,在原有目标后追加:/env:PYTHONPATH="C:\Users\username\AppData\Local\Programs\Python\Python38\Lib\site-packages"这样只有那个软件会读到这个
PYTHONPATH,彻底和Poetry的虚拟环境隔离开。
问题复现步骤(整理版)
为了方便其他遇到同样问题的人参考,这里整理你提到的复现流程:
- 安装Python 3.12,用pipx遵循官方流程安装Poetry
- 安装Python 3.8,添加系统环境变量:
PYTHONPATH = C:\Users\username\AppData\Local\Programs\Python\Python38\Lib\site-packages - 在Python 3.8全局环境执行:
pip install numpy - 用Python 3.12上下文创建Poetry项目:
poetry new testProject - 进入项目目录:
cd testProject,执行poetry add numpy keyboard - 在项目主目录创建
test.py,内容为:import keyboard import numpy - 执行
poetry run .\test.py,会出现numpy导入错误,报错路径指向Python 3.8的全局site-packages - 删除系统环境变量
PYTHONPATH,新开PowerShell窗口执行poetry run .\test.py,运行无错误
备注:内容来源于stack exchange,提问作者Stephen Chipman

