如何在 urllib.urlretrieve 中捕获 404 错误
Posted
技术标签:
【中文标题】如何在 urllib.urlretrieve 中捕获 404 错误【英文标题】:How to catch 404 error in urllib.urlretrieve 【发布时间】:2010-11-21 11:12:52 【问题描述】:背景:我正在使用urllib.urlretrieve
,而不是urllib*
模块中的任何其他功能,因为挂钩功能支持(参见下面的reporthook
).. 用于显示文本进度条。这是 Python >=2.6。
>>> urllib.urlretrieve(url[, filename[, reporthook[, data]]])
但是,urlretrieve
太笨了,以至于无法检测 HTTP 请求的状态(例如:它是 404 还是 200?)。
>>> fn, h = urllib.urlretrieve('http://google.com/foo/bar')
>>> h.items()
[('date', 'Thu, 20 Aug 2009 20:07:40 GMT'),
('expires', '-1'),
('content-type', 'text/html; charset=ISO-8859-1'),
('server', 'gws'),
('cache-control', 'private, max-age=0')]
>>> h.status
''
>>>
下载具有类似钩子的支持(显示进度条)和良好的 HTTP 错误处理的远程 HTTP 文件的最知名方法是什么?
【问题讨论】:
未在您的请求中提供 HTTP 状态可能应该被视为 stdlib 中的错误(但请查看下面更好的库,请求) 这太愚蠢了,urlretrieve 不能用返回状态来处理这个 【参考方案1】:查看urllib.urlretrieve
的完整代码:
def urlretrieve(url, filename=None, reporthook=None, data=None):
global _urlopener
if not _urlopener:
_urlopener = FancyURLopener()
return _urlopener.retrieve(url, filename, reporthook, data)
换句话说,您可以使用urllib.FancyURLopener(它是公共 urllib API 的一部分)。您可以覆盖http_error_default
以检测404:
class MyURLopener(urllib.FancyURLopener):
def http_error_default(self, url, fp, errcode, errmsg, headers):
# handle errors the way you'd like to
fn, h = MyURLopener().retrieve(url, reporthook=my_report_hook)
【讨论】:
我不想指定处理程序;它会抛出像 urllib2.urlopen 这样的异常吗? 很容易让它抛出。 FancyURLopener 子类 URLopener 确实抛出,所以你可以尝试调用基类的实现: def http_error_default(...): URLopener.http_error_default(...) 你应该做 opener = MyURLopener() 然后 opener.retrieve() 来保持 opener 对象活着。否则(如果您在一行上执行所有操作)新创建的开启程序将在检索操作后立即释放。这将在您有机会使用之前删除数据下载到的临时文件。【参考方案2】:你应该使用:
import urllib2
try:
resp = urllib2.urlopen("http://www.google.com/this-gives-a-404/")
except urllib2.URLError, e:
if not hasattr(e, "code"):
raise
resp = e
print "Gave", resp.code, resp.msg
print "=" * 80
print resp.read(80)
编辑:这里的基本原理是,除非您期望异常状态,否则它会发生,您可能甚至都没有考虑过——所以不要让您的代码在失败时继续运行,默认行为是——非常明智地——禁止其执行。
【讨论】:
【参考方案3】:URL Opener 对象的“检索”方法支持报告挂钩并在 404 上引发异常。
http://docs.python.org/library/urllib.html#url-opener-objects
【讨论】:
以上是关于如何在 urllib.urlretrieve 中捕获 404 错误的主要内容,如果未能解决你的问题,请参考以下文章