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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2029523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 23:36:46  来源:igfitidea点击:

How to prevent a module from being imported twice?

pythonimportmodule

提问by KL.

When writing python modules, is there a way to prevent it being imported twice by the client codes? Just like the c/c++ header files do:

编写python模块时,有没有办法防止它被客户端代码导入两次?就像 c/c++ 头文件一样:

#ifndef XXX
#define XXX
...
#endif

Thanks very much!

非常感谢!

回答by Noufal Ibrahim

Python modules aren't imported multiple times. Just running import two times will not reload the module. If you want it to be reloaded, you have to use the reloadstatement. Here's a demo

Python 模块不会多次导入。只运行两次 import 不会重新加载模块。如果要重新加载它,则必须使用该reload语句。这是一个演示

foo.pyis a module with the single line

foo.py是单行的模块

print("I am being imported")

And here is a screen transcript of multiple import attempts.

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

   >>> 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

回答by Ignacio Vazquez-Abrams

Imports are cached, and only run once. Additional imports only cost the lookup time in sys.modules.

导入被缓存,并且只运行一次。额外的导入只会花费sys.modules.

回答by Yoel

As specified in other answers, Pythongenerally doesn't reload a module when encountering a second import statement for it. Instead, it returns its cached version from sys.moduleswithout executing any of its code.

如其他答案中所述,Python在遇到第二个导入语句时通常不会重新加载模块。相反,它在sys.modules不执行任何代码的情况下返回其缓存版本。

However there are several pitfalls worth noting:

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

  • Importing the main module as an ordinary module effectively creates two instances of the same module under different names.

    This occurs because during program startup the main module is set up with the name __main__. Thus, when importing it as an ordinary module, Pythondoesn't detect it in sys.modulesand imports it again, but with its proper name the second time around.

    Consider the file /tmp/a.pywith the following content:

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

    Another file /tmp/b.pyhas a single import statement for a.py(import a).
    Executing /tmp/a.pyresults in the following output:

    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
    

    Therefore, it is best to keep the main module fairly minimal and export most of its functionality to an external module, as advised here.

  • This answerspecifies two more possible scenarios:

    1. Slightly different import statements utilizing different entries in sys.pathleading to the same module.
    2. Attempting another import of a module after a previous one failed halfway through.
  • 将主模块作为普通模块导入可以有效地以不同的名称创建同一模块的两个实例。

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

    考虑具有以下内容的文件/tmp/a.py

    # /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 会产生以下输出:

    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
    

    因此,最好是保持主模块相当小,且大部分的功能导出到外部模块,如建议在这里

  • 此答案指定了另外两种可能的情况:

    1. 稍微不同的导入语句使用不同的条目来sys.path引导同一个模块。
    2. 在前一个模块中途失败后尝试再次导入模块。