|
Python 的模塊一旦加載就會(huì)常駐內(nèi)存,直到程序結(jié)束。再碰到 import 語句式只是修改名字空間,而不需要重新加載。這種機(jī)制是出于運(yùn)行時(shí)的效率考慮,每遇到 import 的時(shí)候重新加載顯然很低效。它也不會(huì)檢查源文件的修改時(shí)間以確定是否重新加載,Python 有那么多的模塊,每次調(diào)用時(shí)都檢查一遍時(shí)間也是不行的。 這種機(jī)制下,開發(fā)長(zhǎng)時(shí)間運(yùn)行的守護(hù)程序就會(huì)很麻煩,修改源代碼后要重新啟動(dòng)程序才能讓新的代碼生效。比如用 mod_python 做 web 開發(fā),Apache 會(huì)啟動(dòng)多個(gè)守護(hù)進(jìn)程來應(yīng)答客戶請(qǐng)求,里面有 python 的解釋引擎和加載的模塊,若要讓修改后的代碼生效只能重起 apache,這會(huì)影響到其它服務(wù)的正常運(yùn)行,非常不方便。mod_python 有一個(gè)PythonAutoReload 參數(shù),它只是針對(duì) PythonHandler 而言的,能夠?qū)υO(shè)定的 PythonHandler 實(shí)現(xiàn)自動(dòng)重新加載,而該 Handler 中所用到的模塊卻不能自動(dòng) reload。 這種修改源代碼然后重起 apache 的調(diào)試方式實(shí)在讓我無法忍受了,決定實(shí)現(xiàn)一種自動(dòng)重新加載機(jī)制。基本的思路就是每個(gè)用戶請(qǐng)求到來時(shí),檢查我所關(guān)心的那些模塊源文件的修改時(shí)間,如果比加載時(shí)的修改時(shí)間新,則重新加載。 編寫一個(gè)檢測(cè)時(shí)間和重新加載的函數(shù),讓它在每個(gè)請(qǐng)求到來時(shí)執(zhí)行:
這段代碼不長(zhǎng),但是改了好多個(gè)版本,最開始用 has_key() 的方式來檢測(cè)是否存在某個(gè)模塊,檢測(cè)該模塊是否有 loadtime 屬性( 用 module.__dict__ ),現(xiàn)在這種方式應(yīng)該效率高一些,曾經(jīng)在一個(gè) blog 上看到過對(duì)比測(cè)試數(shù)據(jù)。起初還在每個(gè)關(guān)心的模塊里面加上一句loadtime = os.path.getmtime( __file__ ),這是不必要的,因?yàn)?Python 用的是動(dòng)態(tài)類型,可以在運(yùn)行時(shí)追加屬性,第一次檢測(cè)時(shí)設(shè)置初始狀態(tài)即可。 有了這段代碼,開發(fā) BlogXP 方便多了,改了源碼之后立馬就能生效,而且它在正常運(yùn)行時(shí)的消耗也很小。另外,由于mod_python 能夠?qū)崿F(xiàn)指定的 Handler 的自動(dòng)重新加載,將這段代碼放在該 Handler 中,可以方便地改變所關(guān)心的模塊列表,也不需重起 apache。 |
|
|