2014-09-21 61 views
0

我是一個相對的Python新手,我對如何正確處理異常感到困惑。爲愚蠢的問題道歉。如何正確使用try/except /內部函數和主

在我的main()中迭代了一個日期列表,併爲每個日期調用一個函數,該函數從公共Web服務器下載一個csv文件。我想明確地理解異常,特別是因爲我不知道何時可以下載感興趣的文件。我的程序將作爲cron作業的一部分執行,並會嘗試每隔3小時下載這些文件(如果可用)。

我想要的是下載日期列表中的第一個文件,如果這導致404,那麼程序不應該繼續下一個文件,因爲假設是如果列表中最早的日期不可用那麼在它後面的其他任何一個都不可用。

我有以下python僞代碼。我試過/除了試圖下載文件的函數內的塊外,但如果函數內部發生異常,我如何在main()中正確處理它,以便我可以決定是否繼續下一個日期。之所以我創建一個函數來執行下載,是因爲我想稍後在同一個main()塊中爲其他文件類型重新使用該代碼。

def main(): 
... 
... 
# datelist is a list of date objects 
    for date in datelist: 
     download_file(date) 

def download_file(date): 
    date_string = str(date.year) + str(date.strftime('%m')) + str(date.strftime('%d')) 
    request = HTTP_WEB_PREFIX+ date_string + FILE_SUFFIX 
    try: 
     response = urllib2.urlopen(request) 
    except urllib2.HTTPError, e: 
     print "HTTPError = " + str(e) 
    except urllib2.URLError, e: 
     print "URLError = " + str(e) 
    except httplib.HTTPException, e: 
     print "HTTPException = " + str(e) 
    except IOError: 
     print "IOError = " + str(e) 
    except Exception: 
     import traceback 
     print "Generic exception: " + traceback.format_exc() 
    else: 
     print "No problem downloading %s - continue..." % (response) 
     try: 
      with open(TMP_DOWNLOAD_DIRECTORY + response, 'wb') as f: 
     except IOError: 
      print "IOError = " + str(e) 
     else: 
      f.write(response.read()) 
     f.close() 

回答

3

這裏的關鍵概念是,如果你能解決問題,你應該捕獲異常;如果你不能,這是處理呼叫者的問題。在這種情況下,如果文件不在那裏,下載程序就無法解決問題,所以它應該將異常情況冒泡給調用者;如果發生異常,調用者應該知道停止循環。

因此,讓我們把所有的異常處理出來的功能進入死循環,所以它胡扯出來,如果有一個失敗的下載文件,爲規範要求修復它:

for date in datelist: 
     date_string = str(date.year) + 
         str(date.strftime('%m')) + 
         str(date.strftime('%d')) 
    try: 
     download_file(date_string) 
    except: 
     e = sys.exc_info()[0] 
     print ("Error downloading for date %s: %s" % (date_string, e)) 
     break 

download_file現在應該,除非你想要重試或類似的東西,根本就不會陷入例外。既然你已經解碼爲您的來電者喜歡的日期,該代碼可以出來的download_file爲好,給簡單得多

def download_file(date_string): 
    request = HTTP_WEB_PREFIX + date_string + FILE_SUFFIX 
    response = urllib2.urlopen(request) 
    print "No problem downloading %s - continue..." % (response) 
    with open(TMP_DOWNLOAD_DIRECTORY + response, 'wb') as f: 
     f.write(response.read()) 
     f.close() 

我將建議print語句是多餘的,但如果你真的想要它,使用logger是一個更加靈活的前進方式,因爲它可以讓你打開或關閉它,以後通過更改配置文件而不是代碼來打開或關閉它。

+0

非常周到的解釋。它幫助我更好地理解所涉及的概念。我很感激。非常感謝你。 – codingknob 2014-09-21 20:37:12

0

從我對您的問題的理解中,您應該將代碼插入到您希望在遇到特定異常時要執行的塊之外。您不必打印遇到的錯誤,您可以在提出任何需要時做任何您認爲有必要的事情......提供帶有信息/選項的彈出框或以其他方式指導您的程序進入下一步。您的其他部分應隔離該部分,因此只有在您的任何異常都未引發時纔會執行。