web-dev-qa-db-fra.com

urllib2.urlopen: "Le nom ou le service n'est pas connu" persiste lorsque vous démarrez un script sans connexion Internet

J'ai ci-dessous cet exemple de «travail» minimal simple qui ouvre une connexion à Google toutes les deux secondes. Lorsque j'exécute ce script alors que la connexion Internet fonctionne, je reçois le message Success, puis lorsque je me déconnecte, je reçois le message Fail et, lorsque je me reconnecte, je reçois le message Success. Jusqu'ici tout va bien.

Cependant, lorsque je lance le script lorsque Internet est déconnecté, je reçois les messages d'échec et lorsque je me connecte plus tard, je ne reçois jamais le message de réussite. Je continue à avoir l'erreur:

erreur urlopen [Errno -2] Nom ou service inconnus

Que se passe-t-il?

import urllib2, time

while True:
    try:
        print('Trying')
        response = urllib2.urlopen('http://www.google.com')
        print('Success')
        time.sleep(2)
    except Exception, e:
        print('Fail ' + str(e))
        time.sleep(2)
14
Ben Ruijl

Cela est dû au fait que le nom DNS "www.google.com" ne peut pas être résolu. S'il n'y a pas de connexion Internet, le serveur DNS n'est probablement pas accessible pour résoudre cette entrée.

Il semble que j'ai mal interprété votre question la première fois. Le comportement que vous décrivez est, sous Linux, une particularité de la glibc. Il ne lit que "/etc/resolv.conf" une fois lors du chargement. La glibc peut être obligée de relire "/etc/resolv.conf" via la fonction res_init().

Une solution serait d’envelopper la fonction res_init() et de l’appeler avant d’appeler getaddrinfo() (utilisé indirectement par urllib2.urlopen().

Vous pouvez essayer ce qui suit (en supposant toujours que vous utilisez Linux):

import ctypes
libc = ctypes.cdll.LoadLibrary('libc.so.6')
res_init = libc.__res_init
# ...
res_init()
response = urllib2.urlopen('http://www.google.com')

Cela pourrait bien sûr être optimisé en attendant que "/etc/resolv.conf" soit modifié avant d'appeler res_init().

Une autre solution consiste à installer, par exemple, nscd (démon de cache de service de noms).

16
insecure

Pour moi, c’était un problème de proxy. Exécuter ce qui suit avant d’importer urllib.request a aidé

import os
os.environ['http_proxy']=''
response = urllib.request.urlopen('http://www.google.com')
0
Sridhar Thiagarajan