Python 的模塊一旦加載就會常駐內存,直到程序結束。再碰到 import 語句式只是修改名字空間,而不需要重新加載。這種機制是出于運行時的效率考慮,每遇到 import 的時候重新加載顯然很低效。它也不會檢查源文件的修改時間以確定是否重新加載,Python 有那么多的模塊,每次調用時都檢查一遍時間也是不行的。
這種機制下,開發長時間運行的守護程序就會很麻煩,修改源代碼后要重新啟動程序才能讓新的代碼生效。比如用 mod_python 做 web 開發,Apache 會啟動多個守護進程來應答客戶請求,里面有 python 的解釋引擎和加載的模塊,若要讓修改后的代碼生效只能重起 apache,這會影響到其它服務的正常運行,非常不方便。mod_python 有一個PythonAutoReload 參數,它只是針對 PythonHandler 而言的,能夠對設定的 PythonHandler 實現自動重新加載,而該 Handler 中所用到的模塊卻不能自動 reload。
這種修改源代碼然后重起 apache 的調試方式實在讓我無法忍受了,決定實現一種自動重新加載機制?;镜乃悸肪褪敲總€用戶請求到來時,檢查我所關心的那些模塊源文件的修改時間,如果比加載時的修改時間新,則重新加載。
編寫一個檢測時間和重新加載的函數,讓它在每個請求到來時執行:
-
def
?autoreload(): ??
-
??mod_names?=?['Entry','Index','SideBar'] ??
-
??
for
?mod_name?
in
?mod_names: ??
-
????
try
: ??
-
??????module?=?
sys
.modules[?mod_name?] ??
-
????
except
: ??
-
??????
continue
??
-
????mtime?=?
os
.path.getmtime(?module.__file__?) ??
-
????
try
: ??
-
??????
if
?mtime?>?module.loadtime: ??
-
????????
reload
(?module?) ??
-
????
except
: ??
-
????
pass
??
-
????module.loadtime?=?mtime ??
這段代碼不長,但是改了好多個版本,最開始用 has_key() 的方式來檢測是否存在某個模塊,檢測該模塊是否有 loadtime 屬性( 用 module.__dict__ ),現在這種方式應該效率高一些,曾經在一個 blog 上看到過對比測試數據。起初還在每個關心的模塊里面加上一句loadtime = os.path.getmtime( __file__ ),這是不必要的,因為 Python 用的是動態類型,可以在運行時追加屬性,第一次檢測時設置初始狀態即可。
有了這段代碼,開發 BlogXP 方便多了,改了源碼之后立馬就能生效,而且它在正常運行時的消耗也很小。另外,由于mod_python 能夠實現指定的 Handler 的自動重新加載,將這段代碼放在該 Handler 中,可以方便地改變所關心的模塊列表,也不需重起 apache。
歡迎批評指正:-)
from: http://blog.daviesliu.net/article/entry20050610-235635