如何正确使用try / except / with inside functions和main

时间:2014-09-21 18:54:10

标签: python with-statement try-except

我是一个相对的python新手,我对如何正确处理异常感到困惑。为愚蠢的问题道歉。

在我的main()中,我遍历一个日期列表,并为每个日期调用一个函数,该函数从公共Web服务器下载csv文件。我想以明显的理由正确捕获异常,但特别是因为我不知道何时可以下载感兴趣的文件。我的程序将作为cron作业的一部分执行,如果可用,将每隔3小时尝试下载这些文件。

我想要的是下载日期列表中的第一个文件,如果这导致404,那么程序不应该继续下一个文件,因为假设列表中最旧的日期不可用,那么其后的其他人也不会出现。

我有以下python伪代码。我在尝试下载文件的函数内部尝试了/ except块但是如果函数内部发生了异常,我如何在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()

2 个答案:

答案 0 :(得分:4)

这里的关键概念是,如果你能解决问题,你应该捕获异常;如果你不能,那就是打电话的问题。在这种情况下,如果文件不在那里,下载程序无法解决问题,因此它应该将其异常冒泡到调用者;如果有异常,调用者应该知道停止循环。

因此,让我们将所有异常处理从函数中移出到循环中,并修复它,以便在下载文件时失败,如规范要求:

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是一种更灵活的前进方式,因为它可以让你打开或关闭它您稍后会更改配置文件而不是代码。

答案 1 :(得分:0)

根据我对您的问题的理解......您应该在遇到特定异常时将代码插入要执行的except块中。您不必打印出遇到的错误,您可以在升级时执行任何您认为必要的操作...提供一个包含信息/选项的弹出框,或者将程序指向下一步。您的其他部分应该隔离该部分,因此只有在没有引发任何异常时才会执行。