Comment puis-je trouver des adresses IP locales (c'est à dire 192.168.x.x ou 10.0.x.x) en Python plate-forme de manière indépendante et en utilisant uniquement la bibliothèque standard?
Réponses
Trop de publicités?Je viens de trouver cela, mais il semble un peu hackish, cependant, disent-ils essayé sur *nix et je l'ai fait sur windows et ça a fonctionné.
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("gmail.com",80))
print(s.getsockname()[0])
s.close()
Cela suppose que vous avez un accès à internet, et qu'il n'y a pas de proxy local.
import socket
socket.gethostbyname(socket.gethostname())
Cela ne fonctionne pas toujours (renvoie 127.0.0.1 sur des machines ayant le nom d'hôte dans le fichier /etc/hosts 127.0.0.1), un accompagnement serait ce que gimel montre, l'utilisation de socket.getfqdn() à la place. Bien sûr, votre machine a besoin d'un nom d'hôte peut être résolu.
import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
Je suis avec cela, parce que l'un des ordinateurs que j'était sur eu un /etc/hosts avec les doublons et les références à lui-même. socket.gethostbyname() ne renvoie que la dernière entrée dans /etc/hosts. Cette solution élimine ceux commençant par "127.". Fonctionne avec Python 3 et 2.5, peut-être d'autres versions. Ne pas traiter avec plusieurs périphériques réseau ou IPv6. Fonctionne sur Linux et Windows.
Mise à jour: La technique ci-dessus cessé de travailler sur les dernières distributions Linux. Ceci peut être utilisé à la place:
import socket
print([(s.connect(('8.8.8.8', 80)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])
Vous pouvez utiliser le netifaces module. Il suffit de taper:
easy_install netifaces
dans votre invite de commande et il va s'installer sur le défaut d'installation de Python.
Ensuite, vous pouvez l'utiliser comme ceci:
from netifaces import interfaces, ifaddresses, AF_INET
for ifaceName in interfaces():
addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}] )]
print '%s: %s' % (ifaceName, ', '.join(addresses))
Sur mon ordinateur, de l'imprimer:
{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207
L'auteur de ce module réclamations il devrait fonctionner sur Windows, UNIX et Mac OS X.
API Socket méthode
import socket
# from http://commandline.org.uk/python/how-to-find-out-ip-address-in-python/
def getNetworkIp():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('INSERT SOME TARGET WEBSITE.com', 0))
return s.getsockname()[0]
Inconvénients:
- Pas de croix-plateforme.
- Nécessite plus de secours code, liés à l'existence des adresses sur internet
- Cela ne fonctionnera pas si vous êtes derrière un NAT
- Probablement crée une connexion UDP, non indépendant (généralement FAI) la disponibilité du DNS (voir les autres réponses pour des idées comme l'utilisation de 8.8.8.8: Google (coïncidence aussi DNS) un serveur)
- Mauvaise forme à intégrer tiers dépendance (par exemple,
google.com
) dans le code comme un moyen de spécifier l'interface réseau, sauf si vous souhaitez l'adresse IP publique de l'interface qui vous redirigera vers le site web spécifique que vous voulez.
Réflecteur méthode
(Notez que cela ne répond pas à l'OP de la question de l'adresse IP locale, par exemple 192.168...; il vous donne votre adresse IP publique, qui pourrait être plus souhaitable, selon les cas d'utilisation.)
Vous pouvez interroger certains sites comme whatismyip.com (mais avec une API), tels que:
from urllib.request import urlopen
import re
def getPublicIp():
data = str(urlopen('http://checkip.dyndns.com/').read())
# data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'
return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)
ou, si vous utilisez python2:
from urllib import urlopen
import re
def getPublicIp():
data = str(urlopen('http://checkip.dyndns.com/').read())
# data = '<html><head><title>Current IP Check</title></head><body>Current IP Address: 65.96.168.198</body></html>\r\n'
return re.compile(r'Address: (\d+\.\d+\.\d+\.\d+)').search(data).group(1)
Avantages:
- Un autre avantage de cette méthode est qu'il est multi-plateforme
- Il travaille à partir de derrière laid NATs (par exemple, votre routeur domestique).
Inconvénients (et les solutions):
- Nécessite de ce site web, le format change pas (presque certainement ne va pas), et de vos serveurs DNS de travail. On peut atténuer ce problème en interrogeant d'autres tiers adresse IP réflecteurs en cas de panne.
- Vecteur d'attaque Possible si vous n'avez pas de requête de plusieurs réflecteurs (pour éviter un compromis réflecteur de vous dire que votre adresse est quelque chose qu'il n'est pas), ou si vous n'utilisez pas le protocole HTTPS (pour éviter un man-in-the-middle attack prétendant être le serveur)
edit: Si au départ j'ai pensé que ces méthodes ont été vraiment mauvais (sauf si vous utilisez plusieurs issues, le code peut être pas pertinent de nombreuses années à partir de maintenant), il pose la question "qu'est-ce que l'internet?". Un ordinateur peut avoir de nombreux liens pointant vers beaucoup de différents réseaux. Pour une description plus détaillée du sujet, google, gateways and routes
. Un ordinateur peut être en mesure d'accéder à un réseau interne via une gateway interne, ou d'accéder à la world-wide web par le biais d'une passerelle, par exemple un routeur (généralement le cas). L'adresse IP locale que l'OP pose des questions sur n'est bien définie par rapport à une seule couche de liaison, de sorte que vous avez à préciser que ("est-ce la carte réseau ou le câble ethernet, ce qui nous parlons?"). Il peut y avoir plusieurs non-uniques réponses à cette question posée. Cependant, l'adresse IP globale sur le world wide web est probablement bien définies (en l'absence de l'immense réseau de la fragmentation): probablement la voie de retour via la passerelle qui peut accéder au Tld.