Python 3.6模块导入错误求助:新增文件无法导入疑因缓存问题
我之前也碰到过一模一样的情况,Python的模块缓存机制有时候确实会搞出这种“明明文件加了却导不进来”的麻烦——尤其是你说的删了模块文件夹、旧代码还能导入的情况,这其实是内存里还存着已加载的模块,再加上字节码缓存的双重作用。下面给你详细说下Python 3.6的缓存位置、清除方法和强制加载的技巧:
一、Python 3.6的模块缓存位置
Python 3.6的字节码缓存(.pyc文件)默认存在每个模块目录下的__pycache__文件夹里,文件名格式是{模块名}.cpython-36.pyc(最后的36对应你的Python版本)。比如你的my_module目录下,新增new_file.py后,第一次导入会生成__pycache__/new_file.cpython-36.pyc。
另外还有个容易被忽略的点:如果你的Python解释器会话还没关闭,已经加载过的my_module会存在内存的sys.modules字典里,这部分是运行时缓存,就算你删了硬盘上的文件和__pycache__,内存里的模块依然有效。
二、清除缓存的方法
1. 删除硬盘上的__pycache__缓存文件夹
这是最直接的方式,找到你的my_module目录,手动删掉里面的__pycache__文件夹就行。如果用命令行:
- Linux/macOS:
rm -rf my_module/__pycache__
- Windows(PowerShell):
Remove-Item -Recurse -Force my_module/__pycache__
2. 清除内存中的模块缓存
如果你的Python会话还在运行(比如在交互式环境里),光删硬盘缓存没用,得把已加载的模块从sys.modules里移除:
import sys # 先删子模块,再删父模块,避免残留 if 'my_module.new_file' in sys.modules: del sys.modules['my_module.new_file'] if 'my_module' in sys.modules: del sys.modules['my_module']
执行完这段再重新导入,就能加载最新的文件了。
3. 启动Python时禁用字节码缓存
如果不想每次都手动删缓存,可以启动Python时加-B参数,这样不会生成.pyc文件,彻底绕过字节码缓存:
python -B your_script.py
或者设置环境变量PYTHONDONTWRITEBYTECODE=1(临时生效,重启终端后消失),效果和-B参数一样。
三、强制加载新文件的技巧
1. 使用importlib.reload()
reload()可以强制重新加载已导入的模块,注意要先导入模块再执行重载:
import my_module import importlib # 重载父模块,这样子模块也会被重新加载 importlib.reload(my_module) # 现在再导入新类就没问题了 from my_module.new_file import new_class
⚠️ 注意:reload()不会更新你已经导入到当前命名空间的对象,比如之前如果已经from my_module import old_class,重载后old_class还是旧的,需要重新导入一次。
2. 手动加载源文件(绕过所有缓存)
如果想彻底绕过缓存,直接从源文件加载,可以用importlib.machinery的SourceFileLoader:
import importlib.machinery import os # 定位到你的new_file.py路径 file_path = os.path.join(os.path.dirname(__file__), 'my_module', 'new_file.py') # 手动加载模块 loader = importlib.machinery.SourceFileLoader('my_module.new_file', file_path) new_module = loader.load_module() # 从模块中获取你要的类 new_class = new_module.new_class
这种方式完全不依赖缓存,每次都会读取最新的源文件内容。
快速排查步骤
给你个一步到位的排查流程:
- 关闭当前所有Python会话(包括交互式环境、运行的脚本)。
- 删除
my_module目录下的__pycache__文件夹。 - 打开新的Python会话,重新执行
from my_module.new_file import new_class。
如果还是不行,就试试在代码里先删除sys.modules里的相关模块,再导入,或者用importlib.reload()。
内容的提问来源于stack exchange,提问作者abinitio

