关于python:如何防止一个模块被导入两次?

How to prevent a module from being imported twice?

在编写python模块时,有没有一种方法可以防止它被客户机代码导入两次?就像C/C++头文件一样:

1
2
3
4
#ifndef XXX
#define XXX
...
#endif

非常感谢!


不能多次导入python模块。只运行导入两次不会重新加载模块。如果您想重新加载它,就必须使用reload语句。这是一个演示

foo.py是一个单线模块。

1
print"I am being imported"

这里是多次导入尝试的屏幕记录。

1
2
3
4
5
   >>> import foo
   Hello, I am being imported
   >>> import foo # Will not print the statement
   >>> reload(foo) # Will print it again
   Hello, I am being imported


导入被缓存,并且只运行一次。额外的导入只占用EDOCX1中的查找时间(0)。


正如其他答案中指定的那样,当遇到模块的第二条导入语句时,Python通常不会重新加载模块。相反,它从sys.modules返回其缓存版本,而不执行任何代码。

然而,有几个陷阱值得注意:

  • 将主模块作为普通模块导入,可以有效地在不同的名称下创建同一模块的两个实例。

    这是因为在程序启动期间,主模块以名称__main__设置。因此,当作为普通模块导入时,python不会在sys.modules中检测到它并再次导入,而是在第二次导入时使用它的正确名称。

    请考虑包含以下内容的文件/tmp/a.py:

    1
    2
    3
    4
    5
    # /tmp/a.py
    import sys

    print"%s executing as %s, recognized as %s in sys.modules" % (__file__, __name__, sys.modules[__name__])
    import b

    另一个文件/tmp/b.py有一个针对a.py的导入语句(import a)。执行/tmp/a.py会导致以下输出:

    1
    2
    3
    root@machine:/tmp$ python a.py
    a.py executing as __main__, recognized as <module '__main__' from 'a.py'> in sys.modules
    /tmp/a.pyc executing as a, recognized as <module 'a' from '/tmp/a.pyc'> in sys.modules

    因此,最好将主模块保持在最低限度,并将其大部分功能导出到外部模块,如本文建议的那样。

  • 这个答案指定了两个可能的场景:

  • 使用sys.path中不同条目的略微不同的导入语句,导致相同的模块。
  • 在前一个模块导入一半后尝试另一个模块导入失败。