2014-01-25 10 views
11

Ich habe dieses einfache, minimale 'Arbeitsbeispiel' unten, das alle zwei Sekunden eine Verbindung zu Google öffnet. Wenn ich dieses Skript ausfühle, wenn ich eine funktionierende Internetverbindung habe, erhalte ich die Erfolgsmeldung, und wenn ich dann die Verbindung abbringe, erhalte ich die Fehlermeldung, und wenn ich die Verbindung wieder herstelle, bekomme ich den Erfolg erneut. So weit, ist es gut.urrlib2.urlopen: "Name oder Dienst nicht bekannt" bleibt beim Starten des Skripts ohne Internetverbindung bestehen

Allerdings, wenn ich das Skript starten, wenn das Internet getrennt ist, bekomme ich die Fail-Nachrichten, und wenn ich später verbinde, bekomme ich nie die Erfolgsmeldung. Ich bekomme immer den Fehler:

urlopen error [Errno -2] Name or service not known

Was ist los?

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) 

Antwort

16

Dies geschieht, weil der DNS-Name "www.google.com" nicht aufgelöst werden kann. Wenn keine Internetverbindung besteht, ist der DNS-Server wahrscheinlich nicht erreichbar, um diesen Eintrag zu lösen.

Es scheint, dass ich Ihre Frage beim ersten Mal falsch gelesen habe. Das Verhalten, das Sie beschreiben, ist unter Linux eine Besonderheit von glibc. Es liest nur einmal "/etc/resolv.conf" beim Laden. glibc kann gezwungen werden, "/etc/resolv.conf" über die res_init() Funktion erneut zu lesen.

Eine Lösung wäre, die res_init() Funktion wickeln und sie aufrufen, bevor getaddrinfo() Aufruf (die indirekt von urllib2.urlopen() verwendet wird

Sie könnten versuchen, die folgenden (noch Sie unter der Annahme, Linux verwenden).

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

Dies könnte natürlich durch das warten optimiert werden, bis „/etc/resolv.conf“ vor res_init() Aufruf geändert wird.

Eine andere Lösung würde ich sein z. B. nscd (Name Service-Cache-Daemon).

+0

Ich war tatsächlich mit Linux. Es ist eine Schande, dass es keine schönere und plattformunabhängige Lösung gibt. Wie auch immer, danke für die Erklärung! –

+1

Nun, ja, es ist nicht plattformunabhängig. Wie auch immer, da es sich um ein Glibc-Problem handelt, sollte folgendes funktionieren, wenn Ihr Code auf anderen Systemen funktionieren muss: 'versuchen Sie: import ... außer: res_init = lambda: None' – insecure

Verwandte Themen