Yun / Python: Offline Yun slow responding to Python try/except

Hello everyone,
i'm writing a yun sketch related to an Rfid tag reader, who passes the code to a python script. If the connection to the internet is available, the scripts checks the code on an online server; otherwise it has to check it on a local DB. Than it has to return a string to Arduino side (using Process.read() ).

To do this on the python side, i've first tried to simply use the try/error method with urllib2 library.

Everything works fine, but to raise the exception the board takes more than 15 seconds, even with timeout (on urllib2.Request) set on 1 second, and socket's default timeout set the same way.

It's to long for my needs.

Running Profile on the python script i've seen that the problem is just the time of rising the exception: every other call takes few milliseconds.

So i tried to bypass the try/except block (using just as last resource if the connection falls) using a simple PING to google.com: i created a simple if statement where if the ping's result is == 0 the scripts runs the online function; otherwise it runs the offline version.

While testing it i've found this stange issue: the first time i run the script it works within 4 seconds even if offline; but than it starts to take more than 15 seconds again to do the same stuff.

#!/usr/bin/python
import urllib, urllib2
import json
import sys
import socket
import profile
import timeit

import os


def connected_to_internet():
    global check_online
    hostname="google.com"
    check_online = os.system("ping -c 1 -s 1 -W 2 " + hostname + " >/dev/null")
    if check_online == 0:
        principale(chiamata_usid, codice)
    
    else:
        funzione_offline(codice)

    return check_online
    
#-----------------------------------------------------------------------------------------------------------------------
def funzione_json():
    global dati_file
    with open(database_file) as dati_json:            # Apre il DB interno come oggetto -dati_json-
        dati_file = json.load(dati_json)                # Decodifica il formato JSON di -dati_json- nel dizionario -dati_file-
        return dati_file
        


def funzione_check_offline(codice, dati_file):    
    global allowed
    for x in range (0, len(dati_file)):                 # Ciclo FOR all'interno del contenuto del dizionario -dati_file-
        if codice==dati_file[x]['usid']:                # Se tra i valori del campo 'usid' trova lo USER ID in uso:
            nome_utente = dati_file[x]['name']          # Inserisce in -nome_utente- il valore di 'name' all'indice corrispettivo
            erogazioni_utente = dati_file[x]['allowed'] # Inserisce in -erogazioni_utente- il valore di 'allowed'
            print "OK,"+nome_utente+",%d,0"%(erogazioni_utente)
                                                        # Crea la stringa di risposta ad ARDUINO con iniziale 'OK,' e dati relativi
                                                        #   termina con '0' (OFFLINE)
            allowed = 1
            break                                       # Interrompe il ciclo FOR
        
    if allowed == 0:                                  # Altrimenti, se il valore di -allowed- e' '0':
        print "KO,0"                                    # Invia ad ARDUINO la risposta 'KO' e il valore '0' (OFFLINE)

    
    
def funzione_offline(codice):
    global dati_file
    funzione_json()
    funzione_check_offline(codice, dati_file)



def principale(chiamata_usid, codice):
    global allowed
    try:                                                    # Se ONLINE
                                                        # Effettua la chiamata per il controllo USER ID al server
        responso_server_usid=urllib2.urlopen(chiamata_usid, timeout = 1) # Riceve la risposta del server
        responso_usid=responso_server_usid.read()           # Inserisce in -responso_usid- la risposta del server
        stringa_utente=json.loads(responso_usid)            # Decodifica il formato JSON della risposta del server in -responso_usid-
        if stringa_utente.has_key('allowed'):               # Se la stringa di risposta del server contiene il valore 'allowed'
            nome_utente=stringa_utente['name']              # Inserisce in -nome_utente- il valore del campo 'name'
            erogazioni_utente=stringa_utente['allowed']     # Inserisce in -erogazioni_utente- il valore del campo 'allowed'
            print "OK,"+nome_utente+",%d,1"%(erogazioni_utente)
                                                        # Crea la stringa di risposta ad ARDUINO con iniziale 'OK,' e dati relativi
                                                        #   termina con '1' (ONLINE)
            allowed=1                                       # Imposta a '1' il valore di ALLOWED
        
    
        if allowed == 0:                                  # Altrimenti, se -allowed- ha valore '0'
            print "KO,1"                                    # Invia ad ARDUINO la stringa 'KO' e il valore 1
        
    except IOError:
        funzione_offline(codice)


    
#-------------------------------------------------------------------------------------------------------------------------
#codice = "55f93eec"

codice=sys.argv[1]                                      # Legge lo USER ID dalla stringa di avvio dello script

#database_file = ("database.json")
database_file = ("/root/database.json")

parametro_usid={}                                       # Crea il dizionario -parametri_usid- per la chiamata ALLOWED
parametro_usid['usid'] = codice                         # Inserisce il valore di -codice- (sys.argv[1]) nel dizionario
#parametro_usid['org'] = 'XXXX'                          # Inserisce il valore XXXX [aggiornare ID PALESTRA] al diz. parametro_usid

parametro_db={}                                         # Crea il dizionario -parametri_db- per la chiamata GET_RESOURCES
parametro_db['org'] = 'XXXX'                            # Inserisce il valore XXXX [aggiornare ID PALESTRA] al diz. -parametro_db-

parametri_url_usid = urllib.urlencode(parametro_usid)   # Codifica i parametri per la chiamata ALLOWED
parametri_url_db = urllib.urlencode(parametro_db)       # Codifica i parametri per la chiamata GET_RESOURCES
    
url={}                                                  # Crea il dizionario -url- con gli indirizzi relativi alle chiamate
url['usid'] = "*************"
url['db'] = "**************"


chiamata_usid= urllib2.Request(url['usid'], parametri_url_usid)

socket.setdefaulttimeout(1.0)
allowed=0                                               # Imposta il valore di ALLOWED a '0'

#----------------------------------------------------------------------------------------------------------------------------------

connected_to_internet()

Why the yun takes so long to react to the absence of internet connection?

Anyone can give me some clue or hints on how to solve this problem?

I guess it should be someting related to the yun (openWrt for example): i've tried the same code on other systems (even updated systems) and it run instantly... Or maybe some memory handling problem... i can't really figure it out...

It's not related to the library urllib2 because the same problem occurs even with other libraries, when coming into a try/except situation related to the absence of internet connetion....

it's driving me crazy....

Thanks everyone...

 responso_server_usid=urllib2.urlopen(chiamata_usid, timeout = 1)

chiamata_usid =?

It's the abstact codification for the url request... You can find it four lines from the end of the script.... However doesn't seem to be a problem....

url['usid'] = "*************"
url['db'] = "**************"
chiamata_usid= urllib2.Request(url['usid'], parametri_url_usid)

The format of url['usid'] ?

url['usid'] = ?

It's the server's url... I can't write it cause i don't own it... But you can even write 'google.com' and remove any parameter in the urllib2 call to the server... The issue doesn't change (at first i've tried to make a generic try/except request to google.com to ensure that the connection was available thinking that the problem was related to the server... It took more than 15 seconds too....).

Thanks in advance however...

Leukos:
It's the server's url... I can't write it cause i don't own it... But you can even write 'google.com' and remove any parameter in the urllib2 call to the server... The issue doesn't change (at first i've tried to make a generic try/except request to google.com to ensure that the connection was available thinking that the problem was related to the server... It took more than 15 seconds too....).

Thanks in advance however...

That is the problem, You can not use "http://www.google.com" here, but http://216.58.219.228" ( 216.58.219.228 is google IP address) other wise DNS lookup will take 15 seconds to time out if no internet connection. change server to IP base then try again.

responso_server_usid=urllib2.urlopen(chiamata_usid, timeout = 1)

"timeout = 1" does not work unless "chiamata_usid" is IP address based.

Thank you so much... I'll try and make you know....

Thank you... seems to work (with google, not directly with the server because is an elastic IP (amazonaws)... I'll try to contact the server admin to solve this (see if he can assign me a static Ip to use)... However thanks again.