多次导入同一Python模块执行过时代码,为何需添加time.sleep(1)?
Python动态生成模块重复导入的版本号问题分析
问题描述
自动生成并多次导入名为mycode的Python模块,期望每次调用fun()输出递增的版本号,但实际始终输出版本0;仅添加time.sleep(1)后才能得到预期结果。
测试代码
import sys import os import time MODULE_NAME = "mycode" def write_module(version): with open(MODULE_NAME+".py", "w") as f: f.write("def fun():"+os.linesep) f.write(" print('Code version:',"+str(version)+")") for i in range(5): # 自动生成Python文件 write_module(i) # 导入模块 if MODULE_NAME in sys.modules: del sys.modules[MODULE_NAME] # time.sleep(1) # 为什么这行是必须的? module = __import__(MODULE_NAME) fun = module.fun # 调用函数 fun()
实际输出
Code version: 0 Code version: 0 Code version: 0 Code version: 0 Code version: 0
预期输出
Code version: 0 Code version: 1 Code version: 2 Code version: 3 Code version: 4
原因分析
核心问题出在操作系统的文件缓存机制:
- 调用
write_module写入文件时,操作系统为了提升性能,不会立刻把内存中的数据写入磁盘,而是先暂存在文件缓存中,等待系统空闲或达到触发条件时再批量刷写到磁盘。 - 当你删除
sys.modules中的模块并重新导入时,Python读取的是磁盘上的旧文件内容(第一次写入的版本0),因为新的内容还停留在操作系统的缓存里,没真正写到磁盘上。 - 添加
time.sleep(1)相当于给了操作系统足够的时间完成缓存刷写,此时重新导入就能读到最新的模块内容。
更优解决方案
不需要依赖time.sleep(),可以通过强制刷写文件的方式,让内容立刻写入磁盘:
修改write_module函数,在写完内容后强制刷新缓冲区并同步到磁盘:
def write_module(version): with open(MODULE_NAME+".py", "w") as f: f.write("def fun():"+os.linesep) f.write(" print('Code version:',"+str(version)+")") f.flush() # 强制将缓冲区内容提交给操作系统 os.fsync(f.fileno()) # 强制操作系统将内容写入磁盘
这样就能在不添加sleep的情况下,每次导入都能读取到最新生成的模块代码,得到预期的递增版本号输出。
内容的提问来源于stack exchange,提问作者Pierrick Pochelu
相关产品推荐
相关产品推荐

