2011-11-14 33 views
3

這可能是一個開放式或尷尬的問題,但我發現自己陷入越來越多的異常處理問題,我不知道處理它們的「最佳」方法。正確處理logging.config.fileConfig拋出的IOError?

如果您嘗試使用不存在的文件配置FileHandler,則Python的日誌記錄模塊會引發IOError。該模塊不處理這個異常,但只是提出它。通常情況下,文件路徑不存在(因此文件不存在),所以如果我們想要處理異常並繼續,我們必須沿路徑創建目錄。

我想讓我的應用程序正確處理這個錯誤,因爲每個用戶都問過爲什麼我們不爲他們製作正確的目錄。

我決定處理這個問題的方式可以在下面看到。

done = False 
while not done: 
    try: 
     # Configure logging based on a config file 
     # if a filehandler's full path to file does not exist, it raises an IOError 
     logging.config.fileConfig(filename) 

    except IOError as e: 
     if e.args[0] == 2 and e.filename: 
      # If we catch the IOError, we can see if it is a "does not exist" error 
      # and try to recover by making the directories 

      print "Most likely the full path to the file does not exist, so we can try and make it" 
      fp = e.filename[:e.rfind("/")] 

      # See http://stackoverflow.com/questions/273192/python-best-way-to-create-directory-if-it-doesnt-exist-for-file-write#273208 for why I don't just leap 
      if not os.path.exists(fp): 
       os.makedirs(fp) 

     else: 
      print "Most likely some other error...let's just reraise for now" 
      raise 
    else: 
     done = True 

我需要循環(或遞歸我想)由於存在需要配置,因此需要ÑIOErrors被升高和用於此方案中校正ÑFileHandlers。

這是正確的方法嗎?有沒有更好,更Python的方式,我不知道或不明白?

+0

我很困惑,不存在的文件是否是配置文件(傳遞給'fileConfig',就像你的源文件一樣)或者它是否是日誌文件的名稱(根據你的問題的文本)嘗試使用不存在的文件配置FileHandler「)。我的答案是後者。通常,在指定文件時(無論是配置文件還是日誌文件),需要確保很多事情 - 例如,文件可能已經存在,但由於權限問題而不可讀或不可寫。沒有一個適合所有人的解決方案,這就是爲什麼你有時需要推出自己的產品。 –

+0

我指的是日誌文件的名稱,我需要從日誌記錄配置文件中取出來檢查它是否存在。必須在代碼中的此處獲取該信息是不方便的。我同意你的觀點,即在啓動時進行檢查是理想的。也許我真正的問題是爲什麼記錄模塊不處理用戶的這些類型的異常? – dicato

+0

由於日誌記錄模塊需要將日誌文件名稱指定爲可寫入文件,並且存在於該目錄中。這種行爲符合最小驚喜的原則。一個典型的文本編輯器(例如,Windows上的記事本或Linux上的gedit),當在不存在的目錄中使用文件名進行調用時,不會自動爲您創建文件。記事本給出錯誤信息; gedit不會以該名稱保存該文件,但會在您單擊「保存」時提示您輸入位置。 –

回答

1

這不是特定於日誌記錄模塊的內容:通常,Python代碼不會自動爲您自動創建中間目錄;你需要做的這個明確使用os.makedirs(),通常是這樣的:

if not os.path.exists(dirname): 
    os.makedirs(dirname) 

您可以替換與子類,可以做你需要的檢查記錄提供的標準FileHandler,在必要時,創建日誌文件的目錄使用os.makedirs()。然後,您可以在配置文件中指定此處理程序,而不是標準處理程序。

+0

因此,爲了正確處理記錄模塊中的異常,我需要繼承模塊?雖然我同意設計是合理的,但它似乎是處理異常(或一組異常)的複雜方式。 – dicato

0

假設只需要在應用程序執行開始時執行一次,我將只需os.makedirs()所有需要的目錄,而不先檢查它們的存在,或者甚至等待記錄模塊發出錯誤。如果您嘗試啓動記錄器時出現錯誤,則可以按照您可能已經執行的方式進行處理:打印錯誤,禁用記錄器。您試圖創建該目錄,超越了自己的想法。如果用戶給你提供虛假信息,那麼你的情況並不比現在差,而且在絕大多數情況下你都會更好。

+0

這種方法令我擔憂的是我需要解析,然後遍歷日誌配置文件,檢查args變量,如果它是文件處理程序,並採取行動。雖然這不是一個挑戰,但它似乎是解決問題的漫長解決方案。爲什麼我需要這樣做?爲什麼記錄模塊不能爲我做這件事? – dicato

+0

Hrm,是啊,我一開始並沒有注意到你傳遞給日誌文件的文件名是那些日誌配置文件而不是日誌文件。它看起來像Vinay有一個建議使用自定義FileHandler這可能是一個更好的方法。 – kindall

+0

雖然Vinay的解決方案當然是一個好主意,但是您認爲這對於這個問題來說是否有點矯枉過正? – dicato