为什么执行期间更改的Python模块会在单独的文件中持续存在?

时间:2017-07-10 22:14:11

标签: python python-3.x interpreted-language

很抱歉标题混乱,让我解释一下我的意思。我使用Google的PrettyTensor API遇到了类似于以下内容的代码,它允许通过@ prettytensor.Register()装饰器将自定义函数添加到PrettyTensor类中。

(位于custom_ops.py)

import prettytensor as pt

@pt.Register(...)
def custom_foo(bar):
    ...

(位于main.py)

import prettytensor as pt
import custom_ops

x = pt.custom_foo(bar)

此代码通过2个单独的文件访问prettytensor,我不明白为什么在一个文件中所做的更改会转移到另一个文件中。同样有趣的是,进口的顺序并不重要。

import custom_ops
import prettytensor as pt

x = pt.custom_foo(bar)

上面的代码仍然可以正常工作。我想帮助找到这种现象的解释,因为我无法在任何地方找到它的文档。在我看来,python解释器正在将模块缓存在内存中,当它被custom_ops文件更改时,它会在再次导入时继续存在于解释器中。如果有人知道为什么会这样,你会怎么阻止它发生?

1 个答案:

答案 0 :(得分:1)

你的模块看到同一版本的prettytensor模块的原因是Python在第一次加载模块时缓存它创建的模块对象。然后可以在不同的地方(或者甚至在同一模块中多次)导入相同的模块模块对象,如果您有理由这样做,而不是从其文件重新加载。

您可以在字典sys.modules中看到已加载的所有模块。每当你对已经加载的模块进行import时,Python就会在sys.modules中看到它并且你将获得对已存在的模块对象的引用,而不是从{加载的新模块{1}}档案。

一般来说,这就是你想要的。如果代码的两个不同部分可以通过两个不同的模块名称获得对从同一文件加载的模块的引用,那通常是一件非常糟糕的事情。例如,您可以拥有两个声称都是类.py的实例的对象,但如果foo.Foo可以,它们可以是两个不同的 foo.Foo类的实例可以通过两种不同方式访问这可以使调试成为一场真正的噩梦。

如果您的Python模块搜索路径混乱(以便包中的模块也在顶层公开),可能会发生重复的模块。它也可能发生在foo模块(从您作为脚本运行的文件中创建)中,也可以使用其常规名称导入(例如__main__,例如main main.py })。

您也可以使用reload功能手动重新加载模块。在Python 2中,这是一个内置的,但它现在在Python 3中隐藏在importlib中。