繁体   English   中英

为什么在Windows上的Python 3下创建模块后导入失败?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM