2013-03-15 79 views
13

我有一個應用程序必須運行一些模擬運行。我想設置一個日誌記錄機制,其中所有日誌記錄都記錄在general.log中,並且模擬運行的所有日誌都轉到run00001.log,....爲此,我定義了一個Run類。在__init__()中爲runlog添加了一個新的文件句柄。python不釋放文件句柄到日誌文件

問題是運行的日誌文件永遠不會被釋放,所以經過多次運行後,可用的句柄耗盡,運行崩潰。

我已經建立了一些程序來測試這個如下

主程序

import Model 
try: 
    myrun = Model.Run('20130315150340_run_49295') 
    ha = raw_input('enter') 
    myrun.log.info("some info") 
except: 
    traceback.print_exc(file=sys.stdout) 

ha = raw_input('enter3') 

類運行的模塊型號定義如下

import logging 
class Run(object): 

    """ Implements the functionality of a single run. """ 
    def __init__(self, runid): 
     self.logdir="." 
     self.runid   = runid 
     self.logFile  = os.path.join(self.logdir , self.runid + '.log') 
     self.log   = logging.getLogger('Run'+self.runid) 
     myformatter   = logging.Formatter('%(asctime)s %(name)-12s %(levelname)-8s %(message)s') 
     myhandler  = logging.FileHandler(self.logFile) 
     myhandler.setLevel(logging.INFO) 
     myhandler.setFormatter(myformatter) 
     self.log.addHandler(myhandler) 

然後我用的是程序進程資源管理器跟隨文件處理程序。我看到runlogs出現,但從不消失。

有沒有辦法強制這個?

+1

爲什麼不能再刪除處理程序運行完成的時候?想必你可以勾起那個事件? – 2013-03-15 15:04:43

+0

有關如何做到這一點的任何建議?我已經嘗試在__del __()中指定self.log.removeHandler(myhandler),即使通過顯式調用析構函數(myrun .__ del __())。我也試過在__exit __()中指定並使用with語句,正如打開文件句柄所建議的那樣。但迄今爲止沒有成功。 – 2013-03-15 19:21:32

+1

您還需要在文件處理程序上調用'.close()'。 'self.log.handlers [0] .close()'應該夠了,真的。 – 2013-03-15 20:47:18

回答

32

您需要在文件處理程序上調用.close()

當你的Run類完成,請致電:

handlers = self.log.handlers[:] 
for handler in handlers: 
    handler.close() 
    self.log.removeHandler(handler) 
+0

不會'[:]'創建處理程序列表的副本? – 2017-10-09 12:01:18

+0

@VasilisLemonidis:是的,就是這一點。您不應該遍歷列表並從中刪除元素,最終會跳過元素。 – 2017-10-09 12:04:35

+0

@VasilisLemonidis:替代方案可以是反向處理元素:'爲反向處理程序(self.log.handlers):...'。 – 2017-10-09 12:05:33