Je veux voir si je peux accéder à une API en ligne, mais pour cela, j'ai besoin d'un accès à Internet.
Comment puis-je voir s'il existe une connexion disponible et active à l'aide de Python?
Peut-être que vous pourriez utiliser quelque chose comme ceci:
import urllib2
def internet_on():
try:
urllib2.urlopen('http://216.58.192.142', timeout=1)
return True
except urllib2.URLError as err:
return False
Actuellement, 216.58.192.142 est l’une des adresses IP de google.com. Changez http://216.58.192.142
en n’importe quel site susceptible de réagir rapidement .
Cette adresse IP fixe ne mappera pas pour toujours à google.com. Donc, ce code est Pas robuste - il aura besoin d’une maintenance constante pour continuer à fonctionner.
La raison pour laquelle le code ci-dessus utilise une adresse IP fixe au lieu d'un nom de domaine complet est due au fait qu'un nom de domaine complet nécessiterait une recherche DNS. Lorsque la machine ne dispose pas d'une connexion Internet fonctionnelle, la recherche DNS elle-même peut bloquer l'appel de urllib_request.urlopen
pendant plus d'une seconde. Merci à @rzetterberg pour l'avoir signalé.
Si l'adresse IP fixe ci-dessus ne fonctionne pas, vous pouvez trouver une adresse IP actuelle pour google.com (sous Unix) en exécutant
% Dig google.com +trace
...
google.com. 300 IN A 216.58.192.142
Si nous pouvons nous connecter à un serveur Internet, nous avons effectivement une connectivité. Cependant, pour une approche rapide et fiable, toutes les solutions doivent au moins respecter les exigences suivantes:
Pour se conformer à ces règles, une solution pourrait consister à vérifier si l’un des serveurs DNS publics de Google est accessible. Les adresses IPv4 de ces serveurs sont 8.8.8.8
et 8.8.4.4
. Nous pouvons essayer de nous connecter à l’un d’eux.
Un rapide Nmap de l'hôte 8.8.8.8
a donné le résultat ci-dessous:
$ 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
Comme nous pouvons le constater, TCP/53 est ouvert et non filtré. Si vous êtes un utilisateur non-root, n'oubliez pas d'utiliser Sudo
ou l'argument -Pn
de Nmap pour envoyer des paquets de sonde conçus et déterminer si l'hôte est actif.
Avant d’essayer avec Python, testons la connectivité à l’aide d’un outil externe, Netcat:
$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!
Netcat confirme que nous pouvons atteindre 8.8.8.8
via TCP/53. Nous pouvons maintenant configurer une connexion de socket à 8.8.8.8:53/TCP en Python pour vérifier la connexion:
>>> 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 Exception as ex:
... print ex.message
... return False
...
>>> internet()
True
>>>
Une autre approche pourrait être d’envoyer une sonde DNS conçue manuellement à l’un de ces serveurs et d’attendre une réponse. Mais, je suppose, la comparaison pourrait s’avérer plus lente en raison de l’abandon de paquets, de l’échec de la résolution DNS, etc. Veuillez commenter si vous pensez le contraire.
UPDATE # 1: Grâce au commentaire de @ theamk, le délai d'attente est maintenant un argument et initialisé à 3 secondes par défaut.
MISE À JOUR # 2: J'ai fait des tests rapides pour identifier l'implémentation la plus rapide et la plus générique de toutes les réponses valides à cette question. Voici le résumé:
$ 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
Et encore une fois:
$ 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
True
dans la sortie ci-dessus signifie que toutes ces implémentations des auteurs respectifs identifient correctement la connectivité à Internet. Le temps est affiché avec une résolution en millisecondes.
UPDATE # 3: Testé à nouveau après le changement de gestion des exceptions:
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
Il sera plus rapide de simplement faire une demande HEAD afin qu'aucun code HTML ne soit récupéré.
De plus, je suis sûr que Google aimerait que cela soit mieux ainsi:)
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
Juste pour mettre à jour ce que dit unutbu pour le nouveau code dans Python 3.2
def check_connectivity(reference):
try:
urllib.request.urlopen(reference, timeout=1)
return True
except urllib.request.URLError:
return False
Et, juste pour noter, l’entrée ici (référence) est l’URL que vous voulez vérifier: je suggère de choisir quelque chose qui se connecte rapidement là où vous vivez - c’est-à-dire que je vis en Corée du Sud, donc je ferais probablement référence à http : //www.naver.com .
En guise d'alternative aux réponses de ubutnu/Kevin C, j'utilise le paquetage requests
comme ceci:
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
Bonus: cela peut être étendu à cette fonction qui ping un site 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
Vous pouvez simplement essayer de télécharger des données, et si la connexion échoue, vous saurez que quelque chose avec la connexion ne va pas bien.
En gros, vous ne pouvez pas vérifier si votre ordinateur est connecté à Internet. Il peut y avoir plusieurs raisons à un échec, comme une configuration DNS incorrecte, des pare-feu, des NAT. Ainsi, même si vous effectuez des tests, vous ne pouvez pas avoir l'assurance que vous aurez une connexion avec votre API jusqu'à ce que vous essayiez.
import urllib
def connected(Host='http://google.com'):
try:
urllib.urlopen(Host)
return True
except:
return False
# test
print( 'connected' if connected() else 'no internet!' )
Pour Python 3, utilisez urllib.request.urlopen(Host)
Essayez l'opération que vous tentiez de faire quand même. Si cela échoue, python devrait vous lancer une exception à vous faire savoir.
Essayer une opération triviale en premier pour détecter une connexion introduira une condition de concurrence critique. Que se passe-t-il si la connexion Internet est valide lorsque vous testez, mais tombe en panne avant que vous ne deviez travailler?
La meilleure façon de le faire est de le vérifier par rapport à une adresse IP que python donne toujours s’il ne trouve pas le site Web. Dans ce cas, c'est mon code:
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("")
Voici ma version
import requests
try:
if requests.get('https://google.com').ok:
print("You're Online")
except:
print("You're Offline")
Cela pourrait ne pas fonctionner si l'hôte local a été changé de 127.0.0.1
Essayez
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 )
Sauf s’il est modifié, l’IP de votre ordinateur sera 127.0.0.1 s’il n’est pas connecté à Internet . Ce code obtient essentiellement l’adresse IP puis demande s’il s’agit de l’adresse IP de l’hôte local . J'espère que cela vous aidera
En prenant la réponse de unutbu comme point de départ et ayant déjà été gravée par une adresse IP "statique", j'ai créé une classe simple qui vérifie une fois en utilisant une recherche DNS (c'est-à-dire, en utilisant l'URL " https://www.google.com "), puis stocke l'adresse IP du serveur qui répond pour une utilisation lors des vérifications suivantes. Ainsi, l’adresse IP est toujours à jour (en supposant que la classe soit réinitialisée au moins une fois tous les deux ou trois ans). Je donne également crédit à gawry pour cette réponse , qui m'a montré comment obtenir l'adresse IP du serveur (après toute redirection, etc.). S'il vous plaît, ne tenez pas compte de l'apparente complexité de cette solution, je vais vous donner un exemple de travail minimal ici. :)
Voici ce que j'ai
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()
Cela fonctionne pour moi dans 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")
En prenant la réponse d'Ivelin et en ajoutant une vérification supplémentaire, mon routeur communique son adresse IP 192.168.0.1 et renvoie un en-tête s'il n'a pas de connexion Internet lorsqu'il interroge google.com.
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
En prenant la réponse de Six, je pense que nous pourrions simplifier d’une manière ou d’une autre, un problème important car les nouveaux arrivants sont perdus dans des domaines très techniques.
Voici ce que je vais enfin utiliser pour attendre que ma connexion (3G, lente) soit établie une fois par jour pour ma surveillance PV.
Fonctionne sous Pyth3 avec 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)
course maximum: 5 minutes si atteint, j'essayerai dans une heure, mais c'est un autre script!
mon préféré, lors de l'exécution de scripts sur un cluster ou non
import subprocess
def online(timeout):
try:
return subprocess.run(
['wget', '-q', '--spider', 'google.com'],
timeout=timeout
).returncode == 0
except subprocess.TimeoutExpired:
return False
wget fonctionne silencieusement, ne télécharge rien mais vérifie que le fichier distant donné existe sur le Web