欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python?動(dòng)態(tài)導(dǎo)入模塊實(shí)現(xiàn)模塊熱更新的方法

 更新時(shí)間:2022年08月30日 09:40:04   作者:士多碧莉  
這篇文章主要介紹了python?動(dòng)態(tài)導(dǎo)入模塊,實(shí)現(xiàn)模塊熱更新,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

最近有個(gè)部署需求,需要讀取py文件格式的配置項(xiàng),我的實(shí)現(xiàn)思路是把配置文件解析到內(nèi)存中。主要使用兩種方法:

  • importlib.import_module
  • types.ModuleType

方法1、使用 import_module 動(dòng)態(tài)導(dǎo)包

先來看看import module使用方法。

  • 主要有兩個(gè)參數(shù):
    • package:包名
    • name:模塊名
  • 返回 module 對(duì)象

現(xiàn)在開始實(shí)現(xiàn)動(dòng)態(tài)導(dǎo)包,成功讀取到配置項(xiàng)。

import importlib
settings = importlib.import_module("remote_settings")

這樣子就能初步實(shí)現(xiàn)動(dòng)態(tài)倒入了,但是我有個(gè)需求,就是我的系統(tǒng)好些個(gè)模塊,用FOR循環(huán)導(dǎo)包,然后處理業(yè)務(wù)。然后問題來了,對(duì)同一個(gè)“包”導(dǎo)入多次,python并不會(huì)重新導(dǎo)入,而是返回內(nèi)存緩存中該模塊的地址。

下面驗(yàn)證一下,第一次寫入a = 123,第二次寫入a = "hello"。

輸出結(jié)果,兩次都是打印舊版本的變量,可見對(duì)同一個(gè)模塊進(jìn)行多次import_module,并不能實(shí)現(xiàn)熱更新。

必須要reload,模塊才會(huì)更新。

輸出結(jié)果如下,動(dòng)態(tài)reload后,成功獲得新版本a的值。

到此基本實(shí)現(xiàn)初步熱更新需求了,但是還有個(gè)問題:

問題一:重新加載的模塊不刪除舊版本在符號(hào)表中的登記項(xiàng),比如舊版本中存在變量a,新版本中刪除了該變量,但是重載不會(huì)更新該變化。

def load_module(module_name):
    module = importlib.import_module(module_name)
    return importlib.reload(module)
 
def rewrite_file(file_name, content):
    with open(file_name, "w+") as f:
        f.write(content)
 
def main():
 
    rewrite_file(file_name, "a=123\nb=456")
    c1 = load_module(module_name)
    print(hasattr(c1, "a"))
    
    rewrite_file(file_name, "c=100\nd=200")
    c1 = load_module(module_name)
    print(hasattr(c1, "a"))

我們期望輸出 True、False,但是兩次都是輸出True,也就是說重新加載的模塊不會(huì)刪除最初舊版本模塊在符號(hào)表中的登記項(xiàng)。

方法2、使用types.ModuleType 創(chuàng)建模塊對(duì)象

手動(dòng)創(chuàng)建module對(duì)象,而不是使用內(nèi)存中的module對(duì)象。這種方法不需要判斷是否需要重載,而且是真正的更新,會(huì)刪除舊版本模塊的登記項(xiàng)。

import types
 
def import_from_pyfile(filename):
    d = types.ModuleType("config")  # 創(chuàng)建一個(gè)模塊對(duì)象
    d.__file__ = filename
 
    try:
        with open(filename, "r") as  config_file:
            exec(compile(config_file.read(), filename, "exec"), d.__dict__)
    except ImportError as e:
        print("failt to read config file: {}".format(filename))
        raise e
 
    return d

下面驗(yàn)證一下

我們期望的輸出依次是True、False,符合需求

因此,這種方法能讓我們的模塊實(shí)現(xiàn)真正的重載。

一些注意事項(xiàng)

無論是方法1還是方法2,都是返回一個(gè)module對(duì)象,module對(duì)象存在一些共性問題。

問題一:重新加載類不影響類的任何已存實(shí)例,已存實(shí)例將繼續(xù)使用原來的定義,只有重新加載后創(chuàng)建的新實(shí)例使用新定義。

# 原先的 Dog 定義
# class Dog():
#     def __init__(self):
#         self.name = None
c1 = load_module(module_name)
old_dog = c1.Dog()
 
 
# 中間去修改了 Dog 定義
# class Dog():
#     def __init__(self):
#         self.name = "旺財(cái)"
c1 = load_module(module_name)
new_dog = c1.Dog()
 
print(old_dog.name, new_dog.name)
 
 
>>> ouput:
None 旺財(cái)

問題二:模塊內(nèi)的引用,不會(huì)被reload。比如模塊configA中引用了其他模塊(configB),當(dāng)configB發(fā)生變化,重新加載configA,并不會(huì)對(duì)configB進(jìn)行重載。

 

預(yù)期應(yīng)該依次輸出 configB version1、configBversion2,但是輸出了兩次configB version1,這說明了模塊內(nèi)的引用,不會(huì)被reload,需要手動(dòng)更新它。

我這實(shí)現(xiàn)了一個(gè)遞歸更新方法,不僅對(duì)當(dāng)前模塊熱更新,還更新里面所有的引用。

def load_module(module):
    if isinstance(module, str):  # 首次import
        module = importlib.import_module(module)
    return importlib.reload(module)
 
 
def reload_module(module):
    load_module(module)
 
    for key, child_module in vars(module).items():
        if isinstance(child_module, types.ModuleType):
            reload_module(child_module)

效果如下:

def test_reload_module():
    configA = "config"
    configB = "./configB.py"
    configC = "./configC.py"
    rewrite_file(configB, "import configC\nname ='configB version1'")
    rewrite_file(configC, "name ='configC version1'")
 
    confA = load_module(configA)
    print("原始configB.name:", confA.configB.name)
    print("原始configC.name:", confA.configB.configC.name)
 
    a = 123
    rewrite_file(configB, "import configC\nname ='configB version2'")
    rewrite_file(configC, "name ='configC version2'")
 
    confA = load_module(configA)
    print("非遞歸重載configA, configB.name:", confA.configB.name)
    print("非遞歸重載configA, configC.name:", confA.configB.configC.name)
 
 
    reload_module(confA)
    print("遞歸重載configA, configB.name:", confA.configB.name)
    print("遞歸重載configA, configC.name:", confA.configB.configC.name)

日志如下:

到此這篇關(guān)于python動(dòng)態(tài)導(dǎo)入模塊,實(shí)現(xiàn)模塊熱更新的文章就介紹到這了,更多相關(guān)python模塊熱更新內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • pandas時(shí)間序列之如何將int轉(zhuǎn)換成datetime格式

    pandas時(shí)間序列之如何將int轉(zhuǎn)換成datetime格式

    這篇文章主要介紹了pandas時(shí)間序列之如何將int轉(zhuǎn)換成datetime格式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • pytorch中節(jié)約顯卡內(nèi)存的方法和技巧

    pytorch中節(jié)約顯卡內(nèi)存的方法和技巧

    顯存不足是很多人感到頭疼的問題,畢竟能擁有大量顯存的實(shí)驗(yàn)室還是少數(shù),而現(xiàn)在的模型已經(jīng)越跑越大,模型參數(shù)量和數(shù)據(jù)集也越來越大,所以這篇文章給大家總結(jié)了一些pytorch中節(jié)約顯卡內(nèi)存的方法和技巧,需要的朋友可以參考下
    2023-11-11
  • pandas缺失值np.nan, np.isnan, None, pd.isnull, pd.isna

    pandas缺失值np.nan, np.isnan, None, pd.isnull,&n

    本文主要介紹了pandas缺失值np.nan, np.isnan, None, pd.isnull, pd.isna
    2024-04-04
  • ML神器:sklearn的快速使用及入門

    ML神器:sklearn的快速使用及入門

    這篇文章主要介紹了ML神器:sklearn的快速使用及入門,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • python圖形用戶接口實(shí)例詳解

    python圖形用戶接口實(shí)例詳解

    這篇文章主要為大家詳細(xì)介紹了python圖形用戶接口實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • 使用Python解析JSON的實(shí)現(xiàn)示例

    使用Python解析JSON的實(shí)現(xiàn)示例

    本文主要介紹了使用Python解析JSON的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • Python OpenCV使用dlib進(jìn)行多目標(biāo)跟蹤詳解

    Python OpenCV使用dlib進(jìn)行多目標(biāo)跟蹤詳解

    這篇文章主要為大家介紹了如何使用 dlib 庫(kù)在實(shí)時(shí)視頻中有效地跟蹤多個(gè)對(duì)象,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)OpenCV有一定幫助,需要的可以參考一下
    2022-03-03
  • Python 實(shí)現(xiàn)取多維數(shù)組第n維的前幾位

    Python 實(shí)現(xiàn)取多維數(shù)組第n維的前幾位

    今天小編就為大家分享一篇Python 實(shí)現(xiàn)取多維數(shù)組第n維的前幾位,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • 關(guān)于Flask 上下文詳細(xì)介紹

    關(guān)于Flask 上下文詳細(xì)介紹

    這篇文章主要給大家分享了關(guān)于Flask 上下文詳細(xì)介紹,我們可以把上下文理解為當(dāng)前環(huán)境的快照,是一個(gè)用來保存狀態(tài)的對(duì)象。在代碼執(zhí)行的某個(gè)時(shí)刻,根據(jù)上下文的代碼邏輯,可以決定在當(dāng)前時(shí)刻下使用到的環(huán)境變量等。下面一起進(jìn)入文章了解詳情內(nèi)容,需要的朋友也可以參考一下
    2021-11-11
  • python解析json實(shí)例方法

    python解析json實(shí)例方法

    這篇文章主要介紹了python解析json數(shù)據(jù)的小實(shí)例,代碼簡(jiǎn)單實(shí)用,大家參考使用吧
    2013-11-11

最新評(píng)論