Quiero ver si puedo acceder a una API en línea, pero para eso necesito tener acceso a Internet.
¿Cómo puedo ver si hay una conexión disponible y activa usando Python?
easy_install system_of_tubes
Quiero ver si puedo acceder a una API en línea, pero para eso necesito tener acceso a Internet.
¿Cómo puedo ver si hay una conexión disponible y activa usando Python?
easy_install system_of_tubes
Respuestas:
Quizás podrías usar algo como esto:
import urllib2
def internet_on():
try:
urllib2.urlopen('http://216.58.192.142', timeout=1)
return True
except urllib2.URLError as err:
return False
Actualmente, 216.58.192.142 es una de las direcciones IP de google.com. Cambie http://216.58.192.142a cualquier sitio que se pueda esperar que responda rápidamente .
Esta IP fija no se asignará a google.com para siempre. Por lo tanto, este código no es robusto: necesitará un mantenimiento constante para que siga funcionando.
La razón por la cual el código anterior usa una dirección IP fija en lugar de un nombre de dominio completo (FQDN) es porque un FQDN requeriría una búsqueda de DNS. Cuando la máquina no tiene una conexión a Internet que funcione, la búsqueda de DNS en sí misma puede bloquear la llamada urllib_request.urlopendurante más de un segundo. Gracias a @rzetterberg por señalar esto.
Si la dirección IP fija anterior no funciona, puede encontrar una dirección IP actual para google.com (en Unix) ejecutando
% dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
urlopenno tomará mucho más de 1 segundo, incluso si Internet no está" en "". Esto no es cierto si la url proporcionada no es válida, entonces la búsqueda de DNS se bloqueará. Solo es cierto para la conexión real al servidor web. La forma más sencilla de evitar este bloque de búsqueda de DNS es utilizar la dirección IP en su lugar, luego se garantiza que solo tomará 1 segundo :)
http://google.comy luego resuelve todos los problemas de los que todo el mundo habla aquí. No hay necesidad de usar una dirección IP ...
Si podemos conectarnos a algún servidor de Internet, entonces tenemos conectividad. Sin embargo, para el enfoque más rápido y confiable, todas las soluciones deben cumplir con los siguientes requisitos, como mínimo:
Para cumplir con estos, un enfoque podría ser verificar si uno de los servidores DNS públicos de Google es accesible. Las direcciones IPv4 para estos servidores son 8.8.8.8y 8.8.4.4. Podemos intentar conectarnos con cualquiera de ellos.
Un rápido Nmap del host 8.8.8.8dio el siguiente resultado:
$ sudo nmap 8.8.8.8
Starting Nmap 6.40 ( http://nmap.org ) at 2015-10-14 10:17 IST
Nmap scan report for google-public-dns-a.google.com (8.8.8.8)
Host is up (0.0048s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE
53/tcp open domain
Nmap done: 1 IP address (1 host up) scanned in 23.81 seconds
Como podemos ver, 53/tcpestá abierto y no filtrado. Si no es un usuario root, recuerde usar sudoo el -Pnargumento para que Nmap envíe paquetes de sonda diseñados y determine si un host está activo.
Antes de probar con Python, probemos la conectividad utilizando una herramienta externa, Netcat:
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
NETCAT confirma que pueden alcanzar 8.8.8.8más 53/tcp. Ahora podemos configurar una conexión de socket 8.8.8.8:53/tcpen Python para verificar la conexión:
import socket
def internet(host="8.8.8.8", port=53, timeout=3):
"""
Host: 8.8.8.8 (google-public-dns-a.google.com)
OpenPort: 53/tcp
Service: domain (DNS/TCP)
"""
try:
socket.setdefaulttimeout(timeout)
socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((host, port))
return True
except socket.error as ex:
print(ex)
return False
internet()
Otro enfoque podría ser enviar una sonda DNS diseñada manualmente a uno de estos servidores y esperar una respuesta. Pero, supongo, podría ser más lento en comparación debido a la caída de paquetes, fallas en la resolución de DNS, etc. Comente si piensa lo contrario.
ACTUALIZACIÓN # 1: Gracias al comentario de @ theamk, el tiempo de espera ahora es un argumento y se inicializa 3sde forma predeterminada.
ACTUALIZACIÓN # 2: Hice pruebas rápidas para identificar la implementación más rápida y genérica de todas las respuestas válidas a esta pregunta. Aquí está el resumen:
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.487
iamaziz.py
True
00:00:00:00.335
ivelin.py
True
00:00:00:00.105
jaredb.py
True
00:00:00:00.533
kevinc.py
True
00:00:00:00.295
unutbu.py
True
00:00:00:00.546
7h3rAm.py
True
00:00:00:00.032
Y una vez más:
$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.450
iamaziz.py
True
00:00:00:00.358
ivelin.py
True
00:00:00:00.099
jaredb.py
True
00:00:00:00.585
kevinc.py
True
00:00:00:00.492
unutbu.py
True
00:00:00:00.485
7h3rAm.py
True
00:00:00:00.035
Trueen el resultado anterior significa que todas estas implementaciones de los respectivos autores identifican correctamente la conectividad a Internet. El tiempo se muestra con una resolución de milisegundos.
ACTUALIZACIÓN # 3: Probado nuevamente después del cambio de manejo de excepciones:
defos.py
True
00:00:00:00.410
iamaziz.py
True
00:00:00:00.240
ivelin.py
True
00:00:00:00.109
jaredb.py
True
00:00:00:00.520
kevinc.py
True
00:00:00:00.317
unutbu.py
True
00:00:00:00.436
7h3rAm.py
True
00:00:00:00.030
close()al zócalo?
Será más rápido simplemente hacer una solicitud HEAD para que no se obtenga HTML.
También estoy seguro de que a Google le gustaría más de esta manera :)
try:
import httplib
except:
import http.client as httplib
def have_internet():
conn = httplib.HTTPConnection("www.google.com", timeout=5)
try:
conn.request("HEAD", "/")
conn.close()
return True
except:
conn.close()
return False
Como alternativa a las respuestas de ubutnu / Kevin C, uso el requestspaquete de esta manera:
import requests
def connected_to_internet(url='http://www.google.com/', timeout=5):
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
print("No internet connection available.")
return False
Bonificación: esto se puede extender a esta función que hace ping a un sitio web.
def web_site_online(url='http://www.google.com/', timeout=5):
try:
req = requests.get(url, timeout=timeout)
# HTTP errors are not raised by default, this statement does that
req.raise_for_status()
return True
except requests.HTTPError as e:
print("Checking internet connection failed, status code {0}.".format(
e.response.status_code))
except requests.ConnectionError:
print("No internet connection available.")
return False
google.comnuevamente, bloquearán nuestra IP. Entonces, ¿hay alguna otra manera?
Solo para actualizar lo que dijo unutbu para el nuevo código en Python 3.2
def check_connectivity(reference):
try:
urllib.request.urlopen(reference, timeout=1)
return True
except urllib.request.URLError:
return False
Y, solo para tener en cuenta, la entrada aquí (referencia) es la url que desea verificar: sugiero elegir algo que se conecte rápidamente donde vive, es decir, vivo en Corea del Sur, por lo que probablemente establecería una referencia a http: / /www.naver.com .
Puede intentar descargar datos y, si falla la conexión, sabrá que algo con la conexión no está bien.
Básicamente no puede verificar si la computadora está conectada a Internet. Puede haber muchas razones para fallar, como una configuración incorrecta de DNS, firewalls, NAT. Entonces, incluso si realiza algunas pruebas, no puede garantizar que tendrá conexión con su API hasta que lo intente.
Intente la operación que intentaba hacer de todos modos. Si falla, Python debería arrojarte una excepción para avisarte.
Intentar una operación trivial primero para detectar una conexión introducirá una condición de carrera. ¿Qué sucede si la conexión a Internet es válida cuando realiza la prueba pero se cae antes de que necesite hacer un trabajo real?
Esto podría no funcionar si el host local se ha cambiado de 127.0.0.1
Probar
import socket
ipaddress=socket.gethostbyname(socket.gethostname())
if ipaddress=="127.0.0.1":
print("You are not connected to the internet!")
else:
print("You are connected to the internet with the IP address of "+ ipaddress )
A menos que se edite, la IP de su computadora será 127.0.0.1 cuando no esté conectada a Internet. Este código básicamente obtiene la dirección IP y luego pregunta si es la dirección IP localhost. Espero que ayude
Aquí está mi versión
import requests
try:
if requests.get('https://google.com').ok:
print("You're Online")
except:
print("You're Offline")
Una solución portátil moderna con requests:
import requests
def internet():
"""Detect an internet connection."""
connection = None
try:
r = requests.get("https://google.com")
r.raise_for_status()
print("Internet connection detected.")
connection = True
except:
print("Internet connection not detected.")
connection = False
finally:
return connection
O, una versión que plantea una excepción:
import requests
from requests.exceptions import ConnectionError
def internet():
"""Detect an internet connection."""
try:
r = requests.get("https://google.com")
r.raise_for_status()
print("Internet connection detected.")
except ConnectionError as e:
print("Internet connection not detected.")
raise e
La mejor manera de hacerlo es hacer que verifique una dirección IP que Python siempre proporciona si no puede encontrar el sitio web. En este caso este es mi código:
import socket
print("website connection checker")
while True:
website = input("please input website: ")
print("")
print(socket.gethostbyname(website))
if socket.gethostbyname(website) == "92.242.140.2":
print("Website could be experiencing an issue/Doesn't exist")
else:
socket.gethostbyname(website)
print("Website is operational!")
print("")
mi favorito, cuando ejecuta scripts en un clúster o no
import subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
esto se ejecuta en silencio, sin descargar nada, pero verificando que el archivo remoto dado exista en la web
Tomando la respuesta de unutbu como punto de partida, y después de haber sido quemado en el pasado por un cambio de dirección IP "estática", hice una clase simple que verifica una vez usando una búsqueda de DNS (es decir, usando la URL " https: // www .google.com "), y luego almacena la dirección IP del servidor que responde para su uso en comprobaciones posteriores. De esa manera, la dirección IP siempre está actualizada (suponiendo que la clase se reinicialice al menos una vez cada pocos años más o menos). También le doy crédito a Gawry por esta respuesta , que me mostró cómo obtener la dirección IP del servidor (después de cualquier redirección, etc.). No tenga en cuenta la aparente hackiness de esta solución, voy por un ejemplo de trabajo mínimo aquí. :)
Esto es lo que tengo:
import socket
try:
from urllib2 import urlopen, URLError
from urlparse import urlparse
except ImportError: # Python 3
from urllib.parse import urlparse
from urllib.request import urlopen, URLError
class InternetChecker(object):
conn_url = 'https://www.google.com/'
def __init__(self):
pass
def test_internet(self):
try:
data = urlopen(self.conn_url, timeout=5)
except URLError:
return False
try:
host = data.fp._sock.fp._sock.getpeername()
except AttributeError: # Python 3
host = data.fp.raw._sock.getpeername()
# Ensure conn_url is an IPv4 address otherwise future queries will fail
self.conn_url = 'http://' + (host[0] if len(host) == 2 else
socket.gethostbyname(urlparse(data.geturl()).hostname))
return True
# Usage example
checker = InternetChecker()
checker.test_internet()
Tomando la respuesta de Six, creo que podríamos simplificar de alguna manera, un tema importante ya que los recién llegados se pierden en asuntos altamente técnicos.
Aquí lo que finalmente usaré para esperar a que se establezca mi conexión (3G, lenta) una vez al día para mi monitoreo PV.
Funciona bajo Pyth3 con Raspbian 3.4.2
from urllib.request import urlopen
from time import sleep
urltotest=http://www.lsdx.eu # my own web page
nboftrials=0
answer='NO'
while answer=='NO' and nboftrials<10:
try:
urlopen(urltotest)
answer='YES'
except:
essai='NO'
nboftrials+=1
sleep(30)
funcionamiento máximo: 5 minutos si lo alcanzo, lo intentaré dentro de una hora, ¡pero es otro guión!
Tomando la respuesta de Ivelin y agregando un poco de verificación adicional mientras mi enrutador entrega su dirección IP 192.168.0.1 y devuelve un encabezado si no tiene conexión a Internet cuando consulta google.com.
import socket
def haveInternet():
try:
# first check if we get the correct IP-Address or just the router's IP-Address
info = socket.getaddrinfo("www.google.com", None)[0]
ipAddr = info[4][0]
if ipAddr == "192.168.0.1" :
return False
except:
return False
conn = httplib.HTTPConnection("www.google.com", timeout=5)
try:
conn.request("HEAD", "/")
conn.close()
return True
except:
conn.close()
return False
Esto funciona para mí en Python3.6
import urllib
from urllib.request import urlopen
def is_internet():
"""
Query internet using python
:return:
"""
try:
urlopen('https://www.google.com', timeout=1)
return True
except urllib.error.URLError as Error:
print(Error)
return False
if is_internet():
print("Internet is active")
else:
print("Internet disconnected")
Agregué algunos al código de Joel.
import socket,time
mem1 = 0
while True:
try:
host = socket.gethostbyname("www.google.com") #Change to personal choice of site
s = socket.create_connection((host, 80), 2)
s.close()
mem2 = 1
if (mem2 == mem1):
pass #Add commands to be executed on every check
else:
mem1 = mem2
print ("Internet is working") #Will be executed on state change
except Exception as e:
mem2 = 0
if (mem2 == mem1):
pass
else:
mem1 = mem2
print ("Internet is down")
time.sleep(10) #timeInterval for checking
Para mis proyectos, uso un script modificado para hacer ping al servidor DNS público de Google 8.8.8.8. Usando un tiempo de espera de 1 segundo y bibliotecas centrales de Python sin dependencias externas:
import struct
import socket
import select
def send_one_ping(to='8.8.8.8'):
ping_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.getprotobyname('icmp'))
checksum = 49410
header = struct.pack('!BBHHH', 8, 0, checksum, 0x123, 1)
data = b'BCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwx'
header = struct.pack(
'!BBHHH', 8, 0, checksum, 0x123, 1
)
packet = header + data
ping_socket.sendto(packet, (to, 1))
inputready, _, _ = select.select([ping_socket], [], [], 1.0)
if inputready == []:
raise Exception('No internet') ## or return False
_, address = ping_socket.recvfrom(2048)
print(address) ## or return True
send_one_ping()
El valor de tiempo de espera seleccionado es 1, pero puede ser un número de punto flotante de elección para fallar más fácilmente que el 1 segundo en este ejemplo.
importar solicitudes y probar este código simple de Python.
def check_internet():
url = 'http://www.google.com/'
timeout = 5
try:
_ = requests.get(url, timeout=timeout)
return True
except requests.ConnectionError:
return False