栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

关于python上的一个坑——reload导致模块重置

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

关于python上的一个坑——reload导致模块重置

在很多时候我们需要动态引入某个库,比如我们需要在服务端和客户端同时引入一个库,他们的文件名一致,如何在运行时对他们进行缓存呢?

下面将举一个很有意思的例子,文件结构如下:

# testlib1/testModule
num = 1
# testlib2/testModule
num = 2
# -*- coding: utf-8 -*-
# 此时有一个需求如下
# 我们需要引入两个文件名相同的python文件
# 且不能静态import 只能调用代码动态reload
import importlib
import os
import sys


# 情况1
class loadModuleCS(object):
    """导入服务端和客户端的库"""

    def __init__(self):
        super(loadModuleCS, self).__init__()
        self.clientModule = None
        self.serverModule = None
        self.loadClientModule()
        self.loadServerModule()

    def _loadModule(self, path):
        """加载path下的模块"""
        name = os.path.basename(path)
        path = path.replace(name, "")
        sys.path.insert(0, path)
        module = importlib.import_module(name.split('.')[0])
        importlib.reload(module)
        print("库里的num为: ", module.num)
        sys.path.pop(0)
        return module

    def loadClientModule(self):
        path = r"F:PythonXSLWorkSpacePythonBaseUsepythonBug1errortestlib1testModule.py"
        self.clientModule = self._loadModule(path)

    def loadServerModule(self):
        path = r"F:PythonXSLWorkSpacePythonBaseUsepythonBug1errortestlib2testModule.py"
        self.serverModule = self._loadModule(path)


loader = loadModuleCS()
print(loader.clientModule.num)
print(loader.serverModule.num)

思考

运行结果如上,思考一个事情:我们在导入的时候库是正确的,那为什么我们重新将 clientModule 和 serverModule 拿出来取里面的值,却不对了?

我们来做一个事情:

loader = loadModuleCS()
print(loader.clientModule.num)
print(loader.serverModule.num)
print(loader.clientModule is loader.serverModule)

打印结果如下:


这下就一目了然了,在这个时候他们实际上同一个东西!也就是说 clientModule 和 serverModule 当前是引用到同一个对象!!why?????

我们都知道,python导入的库都是存放在 sys.modules中, sys.modules 是一个字典,存放了导入的各个模块,会不会就是这一个原因呢?

验证
class loadModuleCS(object):
    """导入服务端和客户端的库"""

    def __init__(self):
        super(loadModuleCS, self).__init__()
        self.clientModule = None
        self.serverModule = None
        self.loadClientModule()
        self.loadServerModule()

    def _loadModule(self, path):
        """加载path下的模块"""
        name = os.path.basename(path)
        path = path.replace(name, "")
        sys.path.insert(0, path)
        module = importlib.import_module(name.split('.')[0])
        importlib.reload(module)
        print("库里的num为: ", module.num)
        print(sys.modules["testModule"])
        sys.path.pop(0)
        return module

    def loadClientModule(self):
        path = r"F:PythonXSLWorkSpacePythonBaseUsepythonBug1errortestlib1testModule.py"
        self.clientModule = self._loadModule(path)

    def loadServerModule(self):
        path = r"F:PythonXSLWorkSpacePythonBaseUsepythonBug1errortestlib2testModule.py"
        self.serverModule = self._loadModule(path)


loader = loadModuleCS()
print(sys.modules["testModule"])
print(loader.clientModule.num)
print(loader.serverModule.num)
print(loader.clientModule is loader.serverModule)
print(loader.clientModule is sys.modules["testModule"], loader.serverModule is sys.modules["testModule"])

此时输出结果如下

验证了我们的猜想,此时 clientModule 和 serverModule 当前是引用到同一个对象

修改方案
    def _loadModule(self, path):
        """加载path下的模块"""
        name = os.path.basename(path)
        path = path.replace(name, "")
        sys.path.insert(0, path)
        moduleName = name.split('.')[0]
        if moduleName in sys.modules:
            sys.modules.pop(moduleName)
        module = importlib.import_module(moduleName)
        importlib.reload(module)
        print("库里的num为: ", module.num)
        print(sys.modules["testModule"])
        sys.path.pop(0)
        return module

此时就符合我们的预期了,clientModule 和 serverModule 分别引用到两个不同的库!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/994405.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号