Python import模塊的緩存問(wèn)題解決方案
在使用django開發(fā)的平臺(tái)中,支持用戶自定義函數(shù),但是每次用戶進(jìn)行修改編輯后,該模塊內(nèi)容已更改,然后重新導(dǎo)入該模塊,但是Python 會(huì)認(rèn)為“我已經(jīng)導(dǎo)入了該模塊,不需要再次讀取該文件”,所以更改將無(wú)效。
因此,每次更改文件的內(nèi)容時(shí),都必須退出并重新啟動(dòng)Django。
使用python開發(fā)后臺(tái)服務(wù)程序的時(shí)候,每次修改代碼之后都需要重啟服務(wù)才能生效比較麻煩
要解決這個(gè)問(wèn)題,有以下幾種方式:
最簡(jiǎn)單、最有效的方法:重新啟動(dòng) Django。但是,這也有缺點(diǎn),特別是丟失了 django名稱空間中存在的數(shù)據(jù)以及其他導(dǎo)入模塊中的數(shù)據(jù)。
對(duì)于簡(jiǎn)單的情況,可以使用 Python 的reload()函數(shù)。在許多情況下,在編輯一個(gè)模塊之后使用
reload()函數(shù)就足夠滿足需求。
這里主要是介紹第二種方式:
reload()是 Python 提供的內(nèi)置函數(shù),在不同的 Python 版本中有不同的表現(xiàn)形式:
在 Python 2.x 中,reload()是內(nèi)置函數(shù)。
在 Python 3.0 - 3.3 中,可以使用imp.reload(module)。
在 Python 3.4 中,imp 已經(jīng)被廢棄,取而代之的是importlib。
Python2.7可以直接用reload():
python2 內(nèi)置函數(shù)reload(module)
Python3可以用下面幾種方法:
方法一:基本方法
from imp import reload reload(module)
方法二:
import imp imp.reload(module)
方法三:
import importlib importlib.reload(module)
方法四:
from importlib import reload reload(module)
說(shuō)明:
module 必須是已經(jīng)成功導(dǎo)入的模塊
模塊被加載到內(nèi)存以后,更改文件內(nèi)容,已經(jīng)運(yùn)行的程序不會(huì)生效的,可通過(guò)reload重新加載。
導(dǎo)入是一個(gè)開銷很大的操作。
python中緩存模塊的一些用法
一.問(wèn)題描述
有時(shí)候可能需要緩存一些 成員方法的值, 可能成員方法的計(jì)算比較耗時(shí),有時(shí)候不希望重復(fù)調(diào)用計(jì)算該值, 這個(gè)時(shí)候就可以緩存該值.
查了一下標(biāo)準(zhǔn)庫(kù) 有 functools.lru_cache 有一個(gè) lru_cache 可以緩存成員函數(shù)的值,
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- """ @author: Frank @contact: frank.chang@shoufuyou.com @file: test_lru_cache.py @time: 2018/9/8 下午8:55 """ import time from functools import lru_cache class Model: @lru_cache(maxsize=10) def calculate(self, number): print(f'calculate({number}) is running,', end=' ') print('sleep 3s ') time.sleep(3) return number * 3 if __name__ == '__main__': model = Model() for i in range(5): print(model.calculate(i)) for i in range(5): print(model.calculate(i))
結(jié)果如下:
calculate(0) is running, sleep 3s
0
calculate(1) is running, sleep 3s
3
calculate(2) is running, sleep 3s
6
calculate(3) is running, sleep 3s
9
calculate(4) is running, sleep 3s
12
0
3
6
9
12
從結(jié)果開出來(lái), 第二次計(jì)算的時(shí)候 , 就沒(méi)有計(jì)算 而是通過(guò)緩存取值, 所以成員方法只計(jì)算了一次.
lru_cache 可以指定 max_size 緩存的大小, typed bool 如果為True, 代表不同類型分別緩存. 如果達(dá)到max_size 淘汰策略是LRU, LRU是Least Recently Used的縮寫,即最近最少使用,常用于頁(yè)面置換算法.
二 第三方的模塊
第三方的模塊cachetools 已經(jīng)提供了很多緩存策略,直接拿來(lái)用一下.
來(lái)看下面的例子.
1 來(lái)看一個(gè)緩存成員方法例子
#!/usr/bin/env python3 # -*- coding: UTF-8 -*- """ @author: Frank @contact: frank.chang@shoufuyou.com @file: test_cache.py @time: 2018/9/8 下午12:59 pip install cachetools https://docs.python.org/3/library/operator.html 緩存成員方法的值 cachetools 已經(jīng)實(shí)現(xiàn)好了, 直接用就可以了. """ from operator import attrgetter import time from cachetools import LRUCache,RRCache , cachedmethod class Model: def __init__(self, cachesize): self.cache = LRUCache(maxsize=cachesize) @cachedmethod(attrgetter('cache')) def get_double_num(self, num): """ return 2* num""" print(f'get_double_num({num}) is running') time.sleep(2) return num * 2 model = Model(cachesize=10) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10)) print(model.get_double_num(10))
結(jié)果如下:
get_double_num(10) is running
20
20
20
20
20
20
Process finished with exit code 0
可以看出, 值計(jì)算一次 函數(shù),第二次走的是緩存. 非常好用. 在初始化方法里面構(gòu)造一個(gè)緩存對(duì)象, 之后用 cachedmethod 修飾成員函數(shù),同時(shí) 用attrgetter(‘cache') 把cache 拿到就可以用了.
實(shí)際上 cachetools 實(shí)現(xiàn)了很多緩存策略,具體緩存策略可以參考下面的鏈接.
'Cache', 'LFUCache', 'LRUCache', 'RRCache', 'TTLCache',
‘cached', ‘cachedmethod' 這兩個(gè)分別用來(lái)修飾 函數(shù)和成員方法的.
2 來(lái)看一個(gè) 緩存函數(shù)
# 緩存 函數(shù)的值 from cachetools import cached @cached(cache={}) def fib(n): print((f'fib({n}) is running.')) return n if n < 2 else fib(n - 1) + fib(n - 2) for i in range(20): print('fib(%d) = %d' % (i, fib(i)))
@cached(cache={}) def fun(n): print(f'fun({n}) is runnnig.') time.sleep(3) return n ** 2 if __name__ == '__main__': for _ in range(5): print(fun(4))
如果cache = None , 表示不緩存,該計(jì)算結(jié)果.
結(jié)果如下:
fun(4) is runnnig.
16
16
16
16
16
直接導(dǎo)入 cached 里面 傳入一個(gè)字典就可以了,用起來(lái)也比較方便.
實(shí)現(xiàn)分析:
緩存思路大致是一樣的, 首先先把參數(shù)hash 一下生成一個(gè)key, 然后看key 是否在自己的緩存里,不在就計(jì)算方法(函數(shù)),之后把key和對(duì)應(yīng)value 放到自己的子弟那里面. 如果下一次計(jì)算該值,生成一個(gè)key 看是否在 自己的字典里面,如果在直接返回即可. 當(dāng)然這是基本的思路, 里面還有用到 緩存淘汰策略, 多線程是否要加鎖,等比較復(fù)雜的問(wèn)題.
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
PPOCRLabel標(biāo)注的txt格式如何轉(zhuǎn)換成labelme能修改的json格式
這篇文章主要介紹了PPOCRLabel標(biāo)注的txt格式如何轉(zhuǎn)換成labelme能修改的json格式問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03在Python中處理時(shí)間之clock()方法的使用
這篇文章主要介紹了在Python中處理時(shí)間之clock()方法的使用,是Python入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-05-05python+selenium 腳本實(shí)現(xiàn)每天自動(dòng)登記的思路詳解
這篇文章主要介紹了python+selenium 腳本實(shí)現(xiàn)每天自動(dòng)登記,本文你給大家分享基本的思路,通過(guò)實(shí)例代碼截圖的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03python之如何使用openpyxl設(shè)置單元格樣式
這篇文章主要介紹了python之如何使用openpyxl設(shè)置單元格樣式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-06-06Python獲取江蘇疫情實(shí)時(shí)數(shù)據(jù)及爬蟲分析
為了關(guān)注疫情狀況,今天我們用python來(lái)爬一爬疫情的實(shí)時(shí)數(shù)據(jù),本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-08-08python中shapefile庫(kù)讀取shapefile文件信息
本文主要介紹了python中shapefile庫(kù)讀取shapefile文件信息,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06