68

I'm using the timeout parameter within the urllib2's urlopen.

urllib2.urlopen('http://www.example.org', timeout=1)

How do I tell Python that if the timeout expires a custom error should be raised?


Any ideas?

RadiantHex
  • 24,907
  • 47
  • 148
  • 244
  • 3
    Note: [`timeout` parameter doesn't limit neither the *total* connection time nor *total* read (response) time.](http://stackoverflow.com/a/32684677/4279) – jfs Dec 05 '15 at 17:37

2 Answers2

105

There are very few cases where you want to use except:. Doing this captures any exception, which can be hard to debug, and it captures exceptions including SystemExit and KeyboardInterupt, which can make your program annoying to use..

At the very simplest, you would catch urllib2.URLError:

try:
    urllib2.urlopen("http://example.com", timeout = 1)
except urllib2.URLError, e:
    raise MyException("There was an error: %r" % e)

The following should capture the specific error raised when the connection times out:

import urllib2
import socket

class MyException(Exception):
    pass

try:
    urllib2.urlopen("http://example.com", timeout = 1)
except urllib2.URLError, e:
    # For Python 2.6
    if isinstance(e.reason, socket.timeout):
        raise MyException("There was an error: %r" % e)
    else:
        # reraise the original error
        raise
except socket.timeout, e:
    # For Python 2.7
    raise MyException("There was an error: %r" % e)
dbr
  • 165,801
  • 69
  • 278
  • 343
  • 5
    This will not work in Python 2.7, as URLError does not catch socket.timeout anymore – Tal Weiss May 14 '13 at 06:20
  • @TalWeiss thanks, added an additional catch for `socket.timeout` – dbr May 14 '13 at 13:34
  • 2
    As for Python 2.7.5 timeouts are caught by urllib2.URLError. – Nicolas L May 18 '14 at 11:58
  • @dbr Thanks, moreover it should be `hasattr(e,'reason') and isinstance(e.reason, socket.timeout)` as `HttpError` at least doesn't have a `reason` attribute in Python 2.6. – Artem Tsikiridis Aug 20 '14 at 15:27
  • I don't understand Tal and Nicolas's comments, but `socket.timeout` works for me with Python 2.7.6. – jds Feb 17 '15 at 23:12
  • 1
    For what it's worth, with python 2.6.6 a timeout trying to connect seems to result in the `urllib2.URLError`. A timeout while reading the response from a slow server seems to result in `socket.timeout`. So overall, catching both allows you to distinguish these cases. – Kay Mar 28 '16 at 15:50
  • I am using python 2.7 and I just could handle TimeoutException with 'urllib2.URLError' instead of 'socket.timeout' – lfvv Apr 17 '17 at 18:20
20

In Python 2.7.3:

import urllib2
import socket

class MyException(Exception):
    pass

try:
    urllib2.urlopen("http://example.com", timeout = 1)
except urllib2.URLError as e:
    print type(e)    #not catch
except socket.timeout as e:
    print type(e)    #catched
    raise MyException("There was an error: %r" % e)
eshizhan
  • 4,235
  • 2
  • 23
  • 23