Comment saisir l'erreur 404 dans urllib.urlretrieve

Background: j'utilise urllib.urlretrieve , contrairement à toute autre fonction dans les modules urllib* , en raison du support de la fonction hook (voir reporthook ci-dessous) .. qui est utilisé pour afficher une barre de progression textuelle. C'est Python >=2.6.

>>> urllib.urlretrieve(url[, filename[, reporthook[, data]]])

cependant, urlretrieve est si stupide qu'il ne laisse aucun moyen de détecter l'état de la requête HTTP (par exemple: était-ce 404 ou 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
''
>>>

Qu'est-ce que le la manière la plus connue de télécharger un fichier HTTP distant avec un support de type hook (pour afficher la barre de progression) et un traitement correct des erreurs HTTP?

26
demandé sur Sridhar Ratnakumar 2009-08-21 00:14:39

3 réponses

Check out urllib.urlretrieve 's code complet:

def urlretrieve(url, filename=None, reporthook=None, data=None):
  global _urlopener
  if not _urlopener:
    _urlopener = FancyURLopener()
  return _urlopener.retrieve(url, filename, reporthook, data)

En d'autres termes, vous pouvez utiliser urllib.FancyURLopener (il fait partie de l'API urllib publique). Vous pouvez remplacer http_error_default pour détecter les 404s:

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)
28
répondu orip 2009-08-20 21:11:37

vous devez utiliser:

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)

Edit: la raison ici est qu'à moins que vous vous attendiez à l'état exceptionnel, c'est une exception pour que cela se produise, et vous n'y avez probablement même pas pensé -- donc au lieu de laisser votre code continuer à fonctionner alors qu'il n'a pas réussi, le comportement par défaut est--très raisonnablement--d'inhiber son exécution.

14
répondu lericson 2010-02-04 20:17:57

la méthode" retreive " de L'objet D'ouverture D'URL supporte le reporthook et jette une exception sur 404.

http://docs.python.org/library/urllib.html#url-opener-objects

2
répondu Mark 2009-08-20 21:13:46