[英]Why does importing a dotted module name fail when upper level is matched by a module in current directory?
[英]Why does importing fail after creating a module under Python 3 on Windows?
以下代码尝试创建然后导入两个模块:
# coding: utf-8
import os
import time
# Remove the modules we're about to create if they already exist
def force_unlink(name):
try:
os.unlink(name)
except OSError:
pass
force_unlink("print1.py")
force_unlink("print1.pyc")
force_unlink("print2.py")
force_unlink("print2.pyc")
time.sleep(1)
# Create module 1 and module 2, then try to import them just afterwards
print("Creating module 1...")
with open("print1.py", "wb+") as fd:
fd.write(b'print("Imported module 1")')
import print1
print("Creating module 2...")
with open("print2.py", "wb+") as fd:
fd.write(b'print("Imported module 2")')
import print2
在Windows上,两种导入均在Python 2(2.7)下工作,但在Python 3(3.5和3.6)下工作:
$ python2 reproduce.py
Creating module 1...
Imported module 1
Creating module 2...
Imported module 2
$ python3 reproduce.py
Creating module 1...
Imported module 1
Creating module 2...
Traceback (most recent call last):
File "reproduce.py", line 26, in <module>
import print2
ImportError: No module named 'print2'
在每个import printX
调用之前添加import printX
time.sleep(5)
使其起作用。
这是为什么?
注意:这是我要解决的问题的简单版本。
我想我知道发生了什么事。 新的Python 3导入机制将在目录中找到的文件名缓存起来。 当目录的修改时间mtime
更改时,它将重新加载缓存。
请参阅importlib._bootstrap_external.FileFinder.find_spec()
方法实现 ,其中包括:
try:
mtime = _path_stat(self.path or _os.getcwd()).st_mtime
except OSError:
mtime = -1
if mtime != self._path_mtime:
self._fill_cache()
self._path_mtime = mtime
这里_path_stat
只是os.stat()
调用,但已本地化以避免导入。 _fill_cache()
方法执行os.listdir()
调用。
在某些Windows文件系统上, mtime
的分辨率非常低,最高可达2秒。 对于您的情况,分辨率显然仍然足够低,以至于在尝试加载第二个模块时, 无法更新缓存。 尽管NTFS文件系统可以以100ns的增量记录时间,但实际上,限制因素似乎是Windows系统时钟,据我了解通常限制为15ms。 因此,如果您在编写print2.py
内编写了print1.py
,那么Python不会注意到。
Python确实为您提供了清除此缓存的方法。 使用importlib.invalidate_caches()
方法 ; 这会将FileFinder
实例上的_path_mtime
属性重置为-1
,从而强制执行新的_fill_cache()
调用。
正如该函数的文档所述:
如果在程序运行时创建/安装了任何模块,则应调用此函数,以确保所有查找者都将注意到新模块的存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.