【问题标题】:Recursive module import and reload递归模块导入和重新加载
【发布时间】:2012-06-12 21:06:39
【问题描述】:

谁能解释为什么要执行以下代码:

文件“hello.py”:

import hello
print "hello"
hello = reload(hello)

python hello.py 执行会打印以下内容?

hello
hello
hello
hello

为什么是 4 次?我知道当一个模块已经被导入时,它不会再次被导入,但是即使它已经被加载,重新加载也会强制重新加载一个模块。结果,我预计会无限次打印“你好”。

reload 不会重新加载模块会发生什么?

【问题讨论】:

    标签: python reload python-import


    【解决方案1】:

    python hello.py (A) 运行代码一次,当 (A) 调用 import hello 时代码再次运行 (B),当 (A) 和 (B) 调用 reload(hello) 时,代码再运行两次,总共四次。

    一般来说,在程序的生命周期中,模块的代码将在以下时间执行:

    • 如果是主模块则一次
    • 当它被任何模块(包括它自己)第一次导入时
    • 任何时候在模块上调用reload()

    至于为什么不递归调用reload(),有一个提前退出点指向PyImport_ReloadModule()函数(CPython,文件为import.c)来防止这种情况:

    http://svn.python.org/view/python/trunk/Python/import.c?view=markup#l2646

        ...
        existing_m = PyDict_GetItemString(modules_reloading, name);
        if (existing_m != NULL) {
            /* Due to a recursive reload, this module is already
               being reloaded. */
            Py_INCREF(existing_m);
            return existing_m;
        }
        ... load module code is below here
    

    【讨论】:

    • 但我想知道为什么在重新加载模块时不会再次调用 reload。如果还有其他原因导致它无法重新加载
    • 这并不能真正解释为什么重新加载中的重新加载不会再次运行代码。
    • 刚刚追踪了 CPython 源代码,了解为什么不会发生重新加载中的重新加载。
    • 如果记忆有用,您曾经可以通过这样做来对 Python 进行段错误。好时光,好时光..
    【解决方案2】:

    reload 保留当前正在重新加载的模块列表(实际上是一个字典),以避免递归地重新加载模块。

    http://hg.python.org/cpython/file/e6b8202443b6/Lib/imp.py#l236

    这并没有记录在案,但我认为你可以依靠它保持这种情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-28
      • 2018-06-14
      • 2019-03-14
      • 2012-12-10
      • 1970-01-01
      • 2018-01-06
      • 1970-01-01
      • 2017-04-03
      相关资源
      最近更新 更多