程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

關於python上的一個坑——reload導致模塊重置

編輯:Python

在很多時候我們需要動態引入某個庫,比如我們需要在服務端和客戶端同時引入一個庫,他們的文件名一致,如何在運行時對他們進行緩存呢?
下面將舉一個很有意思的例子,文件結構如下:

# 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內核浏覽器。


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved