想寫一個通用的decorator限制一個函數的執行時間. python
首先想到的就是把函數執行封在一個線程了,執行結果寫到線程的屬性裏,join指定時間後讀線程的屬性並返回.問題在於若函數沒有執行完,讀不到屬性,返回後.這個線程將繼續存活.在python中,沒法直接殺死一個線程.這個線程也就一直佔用着資源直到線程結束. 函數
一個方法是,讓那個函數或線程週期性的檢測一個標誌位_stopped,若標誌位_stopped被外部賦值True,則再也不執行(直接返回或拋出異常終止).但並非全部函數都能這樣,這個方法略戳.須要改被修飾函數的代碼,不通用. 測試
相似以下函數,在不改動他的前提下限制他的執行時間. spa
def forever(): while True: print('forever') time.sleep(1)這個問題的解以下:
參考:http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python 線程
原理是,從外部讓該線程產生一個異常.詳見該網頁. code
-.- 協程
固然限制任意函數執行時間也能夠經過把函數封在一個進程裏面執行,py的multiprocess中,Process能夠被terminate.也能夠手動給信號發TERM,KILL信號.不過process過重量級了. 進程
另外看了下gevent,gevent的greenlet有kill方法.未測試是否能限制任意函數的執行時間(如上所示那種).目測可行.原理大概是能夠給指定的greenlet生成一個子greenlet,而後在子greenlet中拋出這個異常,這個異常會沿着他的父greenlet一直向上傳.就達到了終止這個greenlet的效果. ip
試了gevent和greenlet.實際是沒法經過協程(greenlet)來實現限制函數執行時間.目測能夠的,從原理上來講不行,實際也不行. 資源
在gevent中有.
gevent.with_timeout(seconds, function, *args, **kwds)
實測該方法沒法限制函數執行時間,目測該方法只能用於非阻塞方法限制執行時間
在greenlet中,嘗試在另外一個線程中對greenlet進行switch會報錯說沒法切換線程.
從原理上來講,greenlet只有一個執行流,切換全是手動的.無法從外部干預這個執行流.