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

2024-04-26 00:08:37 发布

您现在位置:Python中文网/ 问答频道 /正文

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

#ifndef XXX
#define XXX
...
#endif

非常感谢!


Tags: 模块代码客户端头文件xxxendif办法define
3条回答

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

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

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

    这是因为在程序启动期间the main module is set up with the name ^{}。因此,当将其作为普通模块导入时,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.pyimport 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
    

    因此,最好保持主模块相当小,并将其大部分功能导出到外部模块,如建议的here

  • This answer指定了另外两种可能的方案:

    1. 使用sys.path中的不同条目生成相同模块的导入语句略有不同。
    2. 在前一个模块导入中途失败后,尝试另一个模块导入。

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

foo.py是具有单行的模块

print "I am being imported"

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

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

导入被缓存,并且只运行一次。额外的导入只花费了sys.modules中的查找时间。

相关问题 更多 >