为什么我可以从我删除的路径导入模块?

问题描述 投票:0回答:1

tl;dr

我在 /tmp, insert 其道 sys.path,导入虚拟模块。del 不需要了,就把它删掉 sys.path 而我仍然能够导入。为什么要这样做?

完整的问题

考虑这个pytest夹具代码及其注释。

def test_function(temp_dir):
    with open(os.path.join(temp_dir, 'dum.py'), 'w') as f:
        f.write("""
class A:
    \"\"\"
    test docstring
    \"\"\"
    test: int
    test_2: str = "asdf"

class B(A):
    pass
        """)
    import sys
    sys.path.insert(1, temp_dir)
    assert temp_dir in sys.path  # assertion passes
    # noinspection PyUnresolvedReferences
    import dum  # import successful

    yield dum

    # teardown executed after each usage of the fixture
    del dum  # deletion successful
    sys.path.remove(temp_dir)  # removing from path successful
    assert temp_dir not in sys.path  # assertion passes
    with pytest.raises(ModuleNotFoundError):  # fails - importing dum is successful
        import dum

为什么要删除它呢?甚至当我通过执行 sys.path = []. 没有 dum.py 项目目录下的任何地方。我是不是遗漏了什么?Python是否在删除了导入的模块后还在缓存它们?

python pytest python-module
1个回答
6
投票

导入一个模块一次后,下次要导入它时,Python 会首先检查已经导入的模块集合,并使用已经加载的模块。因此,第二次导入模块时。sys.path 甚至没有被查询。

这一点是非常必要的,如果你想一想:假设你直接导入一些模块,每个模块都使用了,其他一些模块,以此类推。如果一个模块必须从磁盘中检索和解析,每次一个 import 语句,你将花费大量的时间来等待模块加载。

同样值得注意的是,当一个模块A第二次导入一个模块B时,实际上什么都不会发生。有一些方法可以显式地重新加载一个已经加载的模块,但通常情况下,你不希望这样做(实时更新的web服务器是一个明显的例外)。


0
投票

伟大而详细的信息是由 Amitai Irron他的回答,所以去那里了解 何以. 回答以下问题: 如何真正去除它 而无法再次导入),你不仅需要对原问题执行全部删除,还需要。

del sys.modules['dum']

这样就可以把这个模块从 sys.modules 其中保留了所有的缓存模块。感谢 0x5453 为我指出 sys.modules.

© www.soinside.com 2019 - 2024. All rights reserved.