在很多時候我們需要動態引入某個庫,比如我們需要在服務端和客戶端同時引入一個庫,他們的文件名一致,如何在運行時對他們進行緩存呢?
下面將舉一個很有意思的例子,文件結構如下:
# testlib1/testModulenum = 1
# testlib2/testModulenum = 2
# -*- coding: utf-8 -*-# 此時有一個需求如下# 我們需要引入兩個文件名相同的python文件# 且不能靜態import 只能調用代碼動態reloadimport importlibimport osimport sys# 情況1class 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:\PythonXSLWorkSpace\PythonBaseUse\pythonBug\1error\testlib1\testModule.py" self.clientModule = self._loadModule(path) def loadServerModule(self): path = r"F:\PythonXSLWorkSpace\PythonBaseUse\pythonBug\1error\testlib2\testModule.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:\PythonXSLWorkSpace\PythonBaseUse\pythonBug\1error\testlib1\testModule.py" self.clientModule = self._loadModule(path) def loadServerModule(self): path = r"F:\PythonXSLWorkSpace\PythonBaseUse\pythonBug\1error\testlib2\testModule.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 分別引用到兩個不同的庫!
作者:在逆境中蛻變
游戲編程,一個游戲開發收藏夾~
如果圖片長時間未顯示,請使用Chrome內核浏覽器。