2009-08-20 16 views
25

Tło: Używam urllib.urlretrieve, w przeciwieństwie do innych funkcji w modułach urllib*, ze względu na wsparcie funkcji hak (patrz reporthook poniżej) .. który jest używany do wyświetlania tekstowych pasek postępu. To jest Python> = 2.6.Jak złapać błąd 404 w urllib.urlretrieve

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

Jednak urlretrieve jest tak głupi, że nie pozostawia sposób wykryć stan żądania HTTP (np: czy to 404 lub 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 
'' 
>>> 

Co jest najbardziej znanym sposobem, aby pobrać plik zdalny HTTP z obsługą haka (aby zobaczyć pasek postępu) i przyzwoitą obsługę błędów HTTP?

+0

Niedostarczenie statusu HTTP na twoje żądanie powinno prawdopodobnie być uznane za błąd w stdlib (ale sprawdź znacznie lepszą bibliotekę, prośby poniżej) –

Odpowiedz

27

Wyjazd urllib.urlretrieve jest kompletny kod:

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

Innymi słowy, można użyć urllib.FancyURLopener (jest to część publicznej urllib API). Można zastąpić http_error_default wykryć błędy 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) 
+0

Nie chcę określać procedur obsługi; czy generuje wyjątki, takie jak urllib2.urlopen? –

+4

Bardzo łatwo jest rzucić. FancyURLopener podklasuje URLopener, który rzuca, więc możesz spróbować wywołać implementację klasy bazowej: def http_error_default (...): URLopener.http_error_default (...) – orip

+0

To jest bardzo dobre rozwiązanie, sam go użyłem. –

14

należy użyć:

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) 

Edytuj: Uzasadnieniem jest to, że jeśli nie spodziewasz się wyjątkowego st zjadł, jest to wyjątek, aby tak się stało, a ty prawdopodobnie nawet o tym nie myślałeś - więc zamiast pozwolić, aby Twój kod działał dalej, gdy się nie powiodło, domyślnym zachowaniem jest - całkiem rozsądnie - zahamowanie jego wykonanie.

+2

wsparcie typu haczyk? –

+1

Sridhar, patrz http://stackoverflow.com/a/9740603/819417 –