2014-09-21 34 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

从我对您的问题的理解中,您应该将代码插入到您希望在遇到特定异常时要执行的块之外。您不必打印遇到的错误,您可以在提出任何需要时做任何您认为有必要的事情......提供带有信息/选项的弹出框或以其他方式指导您的程序进入下一步。您的其他部分应隔离该部分,因此只有在您的任何异常都未引发时才会执行。