Python help, specifically with urllib2

Commissario
Joined
16 Oct 2002
Posts
343,479
Location
In the radio shack
Hi,

I use a Raspberry Pi as an internet watchdog but I'm not entirely convinced I have the code right.

This is supposed to check for the presence of a web site, and wait for up to four minutes for a response.

However, I don't think the timeout bit is working correctly. I think that if it can't access the site it's trying to then it errors straight away.

Here's the full script I'm using. I've part pinched it from the internet and tweaked it a bit.

Code:
import urllib2
import RPi.GPIO as GPIO
import time

RELAY = 21 #RELAY PIN, physical pin 40
ALIVE = 20 #LED PIN to flash LED on live internet, physical pin 38
CHECK_EVERY = 10 #Seconds

GPIO.setmode(GPIO.BCM)
GPIO.setup(RELAY, GPIO.OUT)
GPIO.setup(ALIVE, GPIO.OUT)

# Force both outputs low
GPIO.output(RELAY, GPIO.LOW)
GPIO.output(ALIVE, GPIO.LOW)

def flash_ok():
    GPIO.output(ALIVE, GPIO.HIGH)
        time.sleep(0.2)
        GPIO.output(ALIVE, GPIO.LOW)


def internet_on():
    try:
        response=urllib2.urlopen('https://www.website.com', timeout=240)
          flash_ok()
        return True
    except urllib2.URLError as err: pass
    return False

def reboot_router():
    print "Rebooting Router"
    GPIO.output(RELAY, GPIO.HIGH)
    time.sleep(10) #Energise relay for ten seconds
    GPIO.output(RELAY, GPIO.LOW)
    time.sleep(240) #Wait for four minutes for router to reboot

while True:
    if not internet_on():
        reboot_router()
    time.sleep(CHECK_EVERY)

GPIO.cleanup()

This is the part of the code in question.

Code:
def internet_on():
   try:
        response=urllib2.urlopen('https://www.website.com', timeout=240)
          flash_ok()
        return True
    except urllib2.URLError as err: pass
    return False
Have I got something wrong here, specifically in the timeout bit?

I'm (clearly) not a Python programmer, just someone who finds code and attempts to tweak it!

Thanks for any advice/suggestions.
 
My fault on the copy/paste where I edited out the exact url I'm checking for. Yes it does, I've added it back in the code above, sorry.
 
Good suggestion, thanks.

I've added two lines just to give me an idea of what's happening.

Code:
def internet_on():
    try:
        response=urllib2.urlopen('https://www.unavailable.com', timeout=240)
        print "It's working"
        flash_ok()
        return True
    except urllib2.URLError as err: pass
    print "it's broken"
    return False

And yes, it errors after just a few seconds so the timeout isn't doing what it's supposed to.

The suggestion above about needing a conditional check against socket.timeout may be a good one but I really wouldn't know where to start when it comes to adding that.
 
Right, I tried the first code you've added there, I had to make some changes to actually make it work (all part of the learning process, that's good). It looks like this now:

Code:
def internet_on():
    try:
        response=urllib2.urlopen('https://www.udfsdf5sdg.com', timeout=240)
        print "It's working"
        flash_ok()
        return True
    except urllib2.URLError as err:
        print "It's broken, url error, reason = ", err
    except urllib2.HTTPError as err:
       print "It's broken, http error, reason = ", err
    return False


And you're right, the timeout still does nothing, I get the following after just a few seconds:
Code:
It's broken, url error, reason =  <urlopen error [Errno -2] Name or service not known>

I'm really not sure what that last code segment you've posted is all about.
 
Switching to requests wouldn't be a problem - I just want go get this working (and of course, understand what I'm doing at the same time).
 
That's good, yes I can see that and I can actually see how it's working, thanks.

The web page you're calling doesn't complete the load for five seconds - Providing I increase the setdefaulttimeout to higher than that then I should be OK. If I set it to 180 then it'll wait for three minutes before it errors.

Is that a legit URL to carry on using or is that likely to change? Would using something like google.co.uk be more reliable?

So simply replace

Code:
        response = urllib2.urlopen('http://www.fakeresponse.com/api/?data={"hello":"World"}&sleep=5')

With
Code:
        response = urllib2.urlopen('https://www.google.co.uk')

Looks like I'm nearly there :)
 
Very good, thank you. It's all working now and hopefully I won't get any more false triggers (where it times out too quickly).
 
Back
Top Bottom