2

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

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

我想要的是下载日期列表中的第一个文件,如果结果为 404,则程序不应继续执行下一个文件,因为假设如果列表中最旧的日期不可用,则没有之后的其他人也将可用。

我有以下 python 伪代码。我在尝试下载文件的函数内部有 try/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()
4

2 回答 2

9

这里的关键概念是,如果你能解决问题,你应该捕获异常;如果不能,那就是调用者的问题要处理。在这种情况下,如果文件不存在,下载器将无法修复问题,因此它应该将其异常冒泡给调用者;如果出现异常,调用者应该知道停止循环。

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

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声明是多余的,但是如果您真的想要它,那么 usinglogger是一种更灵活的前进方式,因为这将允许您稍后通过更改配置文件而不是代码来打开或关闭它。

于 2014-09-21T19:38:30.343 回答
0

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

于 2014-09-21T19:31:30.120 回答