• python导入的缓存机制


    问题来源:

    logger文件

    import sys
    
    from loguru import logger
    
    from app.internal.component.configer import settings
    
    
    def configure_logger():
        """
        多进程环境,需要确保子进程能拿到正确初始化的logger实例
        :return:
        """
        logger.remove()
    
    
    logger.add(settings.logFilePath, rotation=settings.logRotation, retention=settings.logRetention,
               enqueue=True, backtrace=True, diagnose=True, level=settings.logLevel,
               format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {file} | {line} |{message}")
    
    logger.add(sys.stderr, enqueue=True, backtrace=True, diagnose=True, level=settings.logLevel,
               format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {file} | {line} | {message}")
    print('load logger')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    main文件中调用
    from app.internal.component.logger import logger
    会执行print语句输出: load logger
    configure_logger()
    然后执行子进程
    每个子进程都会有from app.internal.component.logger import logger
    但没有执行print语句,且Logger.info打印的日志也没有输出

    为什么会这样呢

    可以说明支进程加载logger时是没有真正加载那个文件的;从gpt4上得到的答案:
    Python 的模块导入机制确实包含了一个缓存机制。当你第一次导入一个模块时,Python 会执行两个主要步骤:

    • 加载:Python 查找模块,编译成字节码(如果需要的话),然后执行模块的代码。
    • 缓存:一旦模块被加载,它会被缓存到一个名为 sys.modules 的字典中。
    • sys.modules 字典是 Python 用来跟踪已经加载模块的地方。字典的键是模块的名称,值是模块对象本身。如果你尝试再次导入同一个模块,Python 会首先检查 sys.modules 来看是否已经存在一个条目,如果存在,Python 就会使用缓存的模块而不是重新加载它。这就是为什么模块级别的代码(包括打印语句、函数定义等)只会在第一次导入时执行一次的原因。

    如果你想要看到这个缓存机制的实际效果,你可以这样做:

    import sys
    
    # 查看sys.modules中的条目数量
    print(len(sys.modules))
    
    # 导入一个新模块
    import math
    
    # 再次查看sys.modules中的条目数量,应该增加了
    print(len(sys.modules))
    
    # 再次导入相同的模块并不会增加sys.modules中的条目数量
    import math
    
    # 数量保持不变
    print(len(sys.modules))
    
    # 显示math模块的缓存对象
    print(sys.modules['math'])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这个缓存机制使得模块导入在性能上更加高效,因为它避免了重复的加载和初始化过程。然而,这也意味着如果模块中有可变的状态或者执行了某些操作(比如打印信息),这些只会在第一次导入时发生。

  • 相关阅读:
    Redis漏洞总结--未授权--沙箱绕过--(CNVD-2015-07557)&&(CNVD-2019-21763)&&(CVE-2022-0543)
    深度比较常见库中序列化和反序列化性能的性能差异
    RandomForestClassifier 与 GradientBoostingClassifier 的区别
    网球运动目标检测跟踪
    PYTHON知识点学习-字典
    Java基础-方法-可变参数
    位运算相关笔记
    Jsoup | Document | HTML解析器
    JavaScript判断字符串是否为数字类型:Number.isInteger、isNaN、正则表达式比较
    Servlet API(HttpSerrvlet+HttpServletRequest+HttpServletResponse)
  • 原文地址:https://blog.csdn.net/ningyanggege/article/details/136690945