Py学习  »  Python

为什么在windows上python 3下创建模块后导入会失败?

F.X. • 6 年前 • 2022 次点击  

以下代码尝试创建然后导入两个模块:

# 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上,这两个导入都在Python2(2.7)下工作,但在Python3(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'

添加 time.sleep(5) 在每个 import printX 打电话就行了。

为什么?

注意:这是 issue 我在想办法。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/40012
文章 [ 1 ]  |  最新文章 6 年前
Martijn Pieters
Reply   •   1 楼
Martijn Pieters    7 年前

我想我知道发生了什么。新的python 3进口机器 高速缓存 它在目录中找到的文件名。当 mtime ,目录更改的修改时间。

importlib._bootstrap_external.FileFinder.find_spec() method implementation ,其中包含:

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文件系统中, 纽约时报 是出了名的低,高达2秒。对于您的情况,分辨率显然仍然很低,缓存无法 在尝试加载第二个模块时更新。虽然ntfs文件系统可以以100ns为增量记录时间,但实际上,限制因素似乎是windows系统时钟,据我所知,它通常被限制为15ms的分辨率。 print2.py 写作后15分钟内 print1.py ,则python不会注意到。

python确实提供了清除这个缓存的方法;使用 importlib.invalidate_caches() method ;这将重置 _path_mtime 属性 FileFinder 实例返回到 -1 ,强制 _填充缓存() 打电话。

正如职能部门的文件所述:

如果在程序运行时创建/安装了任何模块,则应调用此函数,以确保所有查找程序都会注意到新模块的存在。