Comment puis-je trouver des adresses IP locales (192.168.x.x ou 10.0.x.x) sur la plateforme Python indépendamment et en utilisant uniquement la bibliothèque standard?
import socket
socket.gethostbyname(socket.gethostname())
Cela ne fonctionnera pas toujours (retourne 127.0.0.1
sur les machines dont le nom d’hôte est /etc/hosts
sous la forme 127.0.0.1
), un paliative serait ce que gimel affiche, utilisez plutôt socket.getfqdn()
. Bien entendu, votre ordinateur a besoin d’un nom d’hôte pouvant être résolu.
Je viens de trouver cela, mais cela semble un peu ridicule, mais ils disent l'avoir essayé sur * nix et je l'ai fait sur les fenêtres et cela a fonctionné.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
Cela suppose que vous avez un accès Internet et qu’il n’existe pas de proxy local.
Comme un alias appelé myip
, cela devrait fonctionner partout:
alias myip="python -c 'import socket; print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith(\"127.\")][:1], [[(s.connect((\"8.8.8.8\", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])'"
Comme ci-dessus, mais uniquement le code Python:
import socket
print([l for l in ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1], [[(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) if l][0][0])
Version qui fonctionnera également sur les réseaux locaux sans connexion Internet:
import socket
print((([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")] or [[(s.connect(("8.8.8.8", 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1]]) + ["no IP found"])[0])
(merci @ccpizza )
Contexte:
L'utilisation de socket.gethostbyname(socket.gethostname())
ne fonctionnait pas ici, car l'un des ordinateurs sur lequel je me trouvais avait un /etc/hosts
avec des entrées en double et des références à lui-même. socket.gethostbyname()
ne renvoie que la dernière entrée dans /etc/hosts
.
C’était ma tentative initiale, qui supprimait toutes les adresses commençant par "127."
:
import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
Cela fonctionne avec Python 2 et 3, sous Linux et Windows, mais ne traite pas avec plusieurs périphériques réseau ou IPv6. Cependant, il n’a plus fonctionné avec les distributions récentes de Linux, j’ai donc essayé cette technique alternative. Il essaie de se connecter au serveur DNS Google à l'adresse 8.8.8.8
au port 53
:
import socket
print([(s.connect(('8.8.8.8', 53)), s.getsockname()[0], s.close()) for s in [socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]][0][1])
Ensuite, j'ai combiné les deux techniques ci-dessus dans une ligne unique qui devrait fonctionner partout, et créé l'alias myip
et l'extrait Python en haut de cette réponse.
Avec la popularité croissante d'IPv6 et pour les serveurs dotés de plusieurs interfaces réseau, l'utilisation d'un module Python tiers pour rechercher l'adresse IP est probablement à la fois plus robuste et fiable que toutes les méthodes répertoriées ici.
Cette méthode renvoie l'adresse IP "principale" de la boîte locale (celle avec une route par défaut).
Python 2 ou 3:
import socket
def get_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
s.close()
return IP
Cela renvoie une seule adresse IP qui est la principale (celle avec une route par défaut). Si vous avez besoin de toutes les adresses IP attachées à toutes les interfaces (y compris localhost, etc.), voir cette réponse .
Si vous êtes derrière un pare-feu NAT tel que votre wifi box chez vous, cela ne montrera pas votre IP publique NAT, mais votre IP privée NAT sur le réseau local qui a une valeur par défaut. route vers votre routeur WIFI local; Obtenir l'IP externe de votre routeur wifi nécessiterait soit de l'exécuter sur That Box, soit de se connecter à un service externe tel que whatismyip.com/whatismyipaddress.com qui pourrait refléter l'IP ... mais cela est complètement différent de la question initiale. :)
Appel mis à jour (connect) par suggestion de Pedro dans les commentaires. (Si vous avez besoin d'une déclaration de licence spécifique, il s'agit d'un domaine public/gratuit pour toute utilisation, ou d'une licence de code/contenu MIT/CC2-BY-SA par pile, selon votre choix.)
Vous pouvez utiliser le module netifaces . Il suffit de taper:
pip install netifaces
dans votre commande Shell et il s’installera lui-même sur l’installation par défaut 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, il imprimait:
{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207
L'auteur de ce module affirme qu'il devrait fonctionner sous Windows, UNIX et Mac OS X.
Méthode de l'API Socket
voir https://stackoverflow.com/a/28950776/711085
Inconvénients:
Méthode du réflecteur
(Notez que cela ne répond pas à la question de l'adresse IP locale posée par l'OP, par exemple 192.168 ...; il vous donne votre adresse IP publique, qui pourrait être plus souhaitable, selon le cas d'utilisation.)
Vous pouvez interroger certains sites tels que 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:
Inconvénients (et solutions de contournement):
edit: Bien qu'initialement je pensais que ces méthodes étaient vraiment mauvaises (à moins que vous n'utilisiez beaucoup de solutions de repli, le code risque de ne plus être pertinent dans plusieurs années), il pose la question "qu'est-ce qu'Internet?". Un ordinateur peut avoir de nombreuses interfaces pointant vers plusieurs réseaux différents. Pour une description plus détaillée du sujet, consultez Google pour gateways and routes
. Un ordinateur peut être en mesure d'accéder à un réseau interne via une passerelle interne ou au Web via une passerelle, par exemple un routeur (généralement le cas). L’adresse IP locale sur laquelle l’opérateur pose des questions n’est définie que de manière précise par rapport à une seule couche de liaison; vous devez donc spécifier cela ("s’agit-il de la carte réseau ou du câble Ethernet dont nous parlons?") . Il peut y avoir plusieurs réponses non uniques à cette question telle que posée. Toutefois, l’adresse IP globale sur le Web est probablement bien définie (en l’absence de fragmentation massive du réseau): probablement le chemin de retour via la passerelle permettant d’accéder aux TLD.
Si l'ordinateur est connecté à Internet, toujours fonctionnera pour obtenir l'adresse IP locale préférée, même si/etc/hosts n'est pas défini correctement.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 1)) # connect() for UDP doesn't send packets
local_ip_address = s.getsockname()[0]
Sous Linux:
>>> import socket, struct, fcntl
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sockfd = sock.fileno()
>>> SIOCGIFADDR = 0x8915
>>>
>>> def get_ip(iface = 'eth0'):
... ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
... try:
... res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
... except:
... return None
... ip = struct.unpack('16sH2x4s8x', res)[2]
... return socket.inet_ntoa(ip)
...
>>> get_ip('eth0')
'10.80.40.234'
>>>
im utilisant le module suivant:
#!/usr/bin/python
# module for getting the lan ip address of the computer
import os
import socket
if os.name != "nt":
import fcntl
import struct
def get_interface_ip(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', bytes(ifname[:15], 'utf-8'))
# Python 2.7: remove the second argument for the bytes call
)[20:24])
def get_lan_ip():
ip = socket.gethostbyname(socket.gethostname())
if ip.startswith("127.") and os.name != "nt":
interfaces = ["eth0","eth1","eth2","wlan0","wlan1","wifi0","ath0","ath1","ppp0"]
for ifname in interfaces:
try:
ip = get_interface_ip(ifname)
break;
except IOError:
pass
return ip
Testé avec Windows et Linux (et ne nécessite pas de modules supplémentaires pour ceux-ci) Destiné à être utilisé sur des systèmes utilisant un seul réseau local basé sur IPv4.
La liste fixe des noms d'interface ne fonctionne pas pour les versions récentes de Linux, qui ont adopté la modification de systemd v197 concernant les noms d'interface prévisibles, comme indiqué par Alexander . Dans ce cas, vous devez remplacer manuellement la liste par les noms d’interface de votre système ou utilisez une autre solution telle que netifaces .
J'utilise ceci sur mes machines Ubuntu:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
Ça ne marche pas.
Si vous ne souhaitez pas utiliser de packages externes et ne souhaitez pas vous fier à des serveurs Internet extérieurs, cela pourrait vous aider. C'est un exemple de code que j'ai trouvé sur Google Code Search et modifié pour renvoyer les informations requises:
def getIPAddresses():
from ctypes import Structure, windll, sizeof
from ctypes import POINTER, byref
from ctypes import c_ulong, c_uint, c_ubyte, c_char
MAX_ADAPTER_DESCRIPTION_LENGTH = 128
MAX_ADAPTER_NAME_LENGTH = 256
MAX_ADAPTER_ADDRESS_LENGTH = 8
class IP_ADDR_STRING(Structure):
pass
LP_IP_ADDR_STRING = POINTER(IP_ADDR_STRING)
IP_ADDR_STRING._fields_ = [
("next", LP_IP_ADDR_STRING),
("ipAddress", c_char * 16),
("ipMask", c_char * 16),
("context", c_ulong)]
class IP_ADAPTER_INFO (Structure):
pass
LP_IP_ADAPTER_INFO = POINTER(IP_ADAPTER_INFO)
IP_ADAPTER_INFO._fields_ = [
("next", LP_IP_ADAPTER_INFO),
("comboIndex", c_ulong),
("adapterName", c_char * (MAX_ADAPTER_NAME_LENGTH + 4)),
("description", c_char * (MAX_ADAPTER_DESCRIPTION_LENGTH + 4)),
("addressLength", c_uint),
("address", c_ubyte * MAX_ADAPTER_ADDRESS_LENGTH),
("index", c_ulong),
("type", c_uint),
("dhcpEnabled", c_uint),
("currentIpAddress", LP_IP_ADDR_STRING),
("ipAddressList", IP_ADDR_STRING),
("gatewayList", IP_ADDR_STRING),
("dhcpServer", IP_ADDR_STRING),
("haveWins", c_uint),
("primaryWinsServer", IP_ADDR_STRING),
("secondaryWinsServer", IP_ADDR_STRING),
("leaseObtained", c_ulong),
("leaseExpires", c_ulong)]
GetAdaptersInfo = windll.iphlpapi.GetAdaptersInfo
GetAdaptersInfo.restype = c_ulong
GetAdaptersInfo.argtypes = [LP_IP_ADAPTER_INFO, POINTER(c_ulong)]
adapterList = (IP_ADAPTER_INFO * 10)()
buflen = c_ulong(sizeof(adapterList))
rc = GetAdaptersInfo(byref(adapterList[0]), byref(buflen))
if rc == 0:
for a in adapterList:
adNode = a.ipAddressList
while True:
ipAddr = adNode.ipAddress
if ipAddr:
yield ipAddr
adNode = adNode.next
if not adNode:
break
Usage:
>>> for addr in getIPAddresses():
>>> print addr
192.168.0.100
10.5.9.207
Comme il repose sur windll
, cela ne fonctionnera que sous Windows.
Je ne crois pas que cette version ait été publiée pour le moment. J'ai testé avec Python 2.7 sur Ubuntu 12.04.
Vous avez trouvé cette solution à: http://code.activestate.com/recipes/439094-get-the-ip-address-associated-with-a-network-inter/
import socket
import fcntl
import struct
def get_ip_address(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', ifname[:15])
)[20:24])
Exemple de résultat:
>>> get_ip_address('eth0')
'38.113.228.130'
Sur Debian (testé) et je soupçonne la plupart des systèmes Linux ..
import commands
RetMyIP = commands.getoutput("hostname -I")
Sur MS Windows (testé)
import socket
socket.gethostbyname(socket.gethostname())
Variation sur la réponse de ninjagecko. Cela devrait fonctionner sur tout réseau local permettant la diffusion UDP et ne nécessitant pas d'accès à une adresse du réseau local ou d'Internet.
import socket
def getNetworkIp():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.connect(('<broadcast>', 0))
return s.getsockname()[0]
print (getNetworkIp())
Un moyen simple de produire une sortie "propre" via des utilitaires en ligne de commande:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips
Il montrera toutes les adresses IPv4 sur le système.
J'ai bien peur qu'il n'y ait pas de bonne façon de procéder, indépendamment de la plate-forme, autre que la connexion à un autre ordinateur et que celui-ci vous envoie votre adresse IP. Par exemple: findmyipaddress . Notez que cela ne fonctionnera pas si vous avez besoin d'une adresse IP située derrière NAT, sauf si l'ordinateur auquel vous vous connectez se trouve également derrière NAT.
Voici une solution qui fonctionne sous Linux: obtenir l’adresse IP associée à une interface réseau .
Ceci est une variante de la réponse de UnkwnTech - elle fournit une fonction get_local_addr()
, qui renvoie l'adresse IP de réseau local principale de l'hôte. Je le publie car cela ajoute un certain nombre d'éléments: prise en charge d'ipv6, traitement des erreurs, ignorant les adresses localhost/linklocal et utilise un compte TESTNET (rfc5737) pour se connecter.
# imports
import errno
import socket
# localhost prefixes
_local_networks = ("127.", "0:0:0:0:0:0:0:1")
# ignore these prefixes -- localhost, unspecified, and link-local
_ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:")
def detect_family(addr):
if "." in addr:
assert ":" not in addr
return socket.AF_INET
Elif ":" in addr:
return socket.AF_INET6
else:
raise ValueError("invalid ipv4/6 address: %r" % addr)
def expand_addr(addr):
"""convert address into canonical expanded form --
no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups.
"""
family = detect_family(addr)
addr = socket.inet_ntop(family, socket.inet_pton(family, addr))
if "::" in addr:
count = 8-addr.count(":")
addr = addr.replace("::", (":0" * count) + ":")
if addr.startswith(":"):
addr = "0" + addr
return addr
def _get_local_addr(family, remote):
try:
s = socket.socket(family, socket.SOCK_DGRAM)
try:
s.connect((remote, 9))
return s.getsockname()[0]
finally:
s.close()
except socket.error:
return None
def get_local_addr(remote=None, ipv6=True):
"""get LAN address of Host
:param remote:
return LAN address that Host would use to access that specific remote address.
by default, returns address it would use to access the public internet.
:param ipv6:
by default, attempts to find an ipv6 address first.
if set to False, only checks ipv4.
:returns:
primary LAN address for Host, or ``None`` if couldn't be determined.
"""
if remote:
family = detect_family(remote)
local = _get_local_addr(family, remote)
if not local:
return None
if family == socket.AF_INET6:
# expand zero groups so the startswith() test works.
local = expand_addr(local)
if local.startswith(_local_networks):
# border case where remote addr belongs to Host
return local
else:
# NOTE: the two addresses used here are TESTNET addresses,
# which should never exist in the real world.
if ipv6:
local = _get_local_addr(socket.AF_INET6, "2001:db8::1234")
# expand zero groups so the startswith() test works.
if local:
local = expand_addr(local)
else:
local = None
if not local:
local = _get_local_addr(socket.AF_INET, "192.0.2.123")
if not local:
return None
if local.startswith(_ignored_networks):
return None
return local
Pour info je peux vérifier que la méthode:
import socket
addr = socket.gethostbyname(socket.gethostname())
Fonctionne sous OS X (10.6,10.5), Windows XP et sur un serveur de département RHEL bien administré. Cela n’a pas fonctionné avec un minimum de CentOS VM sur lequel je viens de faire du piratage du noyau. Donc, pour cette instance, vous pouvez simplement rechercher une adresse 127.0.0.1 et dans ce cas, procédez comme suit:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
Et puis analyser l'adresse ip de la sortie. Il est à noter que ifconfig n'est pas dans le PATH d'un utilisateur normal par défaut et c'est pourquoi je donne le chemin complet dans la commande. J'espère que ça aide.
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
Cela fonctionnera sur la plupart des boîtes Linux:
import socket, subprocess, re
def get_ipv4_address():
"""
Returns IP address(es) of current machine.
:return:
"""
p = subprocess.Popen(["ifconfig"], stdout=subprocess.PIPE)
ifc_resp = p.communicate()
patt = re.compile(r'inet\s*\w*\S*:\s*(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
resp = patt.findall(ifc_resp[0])
print resp
get_ipv4_address()
Cette réponse est ma tentative personnelle de résoudre le problème d'obtention de l'adresse IP du réseau local, puisque socket.gethostbyname(socket.gethostname())
a également renvoyé 127.0.0.1. Cette méthode ne nécessite pas d’Internet mais seulement une connexion LAN. Le code est pour Python 3.x mais pourrait facilement être converti pour 2.x. Utilisation de la diffusion UDP:
import select
import socket
import threading
from queue import Queue, Empty
def get_local_ip():
def udp_listening_server():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('<broadcast>', 8888))
s.setblocking(0)
while True:
result = select.select([s],[],[])
msg, address = result[0][0].recvfrom(1024)
msg = str(msg, 'UTF-8')
if msg == 'What is my LAN IP address?':
break
queue.put(address)
queue = Queue()
thread = threading.Thread(target=udp_listening_server)
thread.queue = queue
thread.start()
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
waiting = True
while waiting:
s2.sendto(bytes('What is my LAN IP address?', 'UTF-8'), ('<broadcast>', 8888))
try:
address = queue.get(False)
except Empty:
pass
else:
waiting = False
return address[0]
if __== '__main__':
print(get_local_ip())
127.0.1.1
est votre adresse IP réelle. Plus généralement, un ordinateur peut avoir un nombre quelconque d'adresses IP. Vous pouvez les filtrer pour les réseaux privés - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 et 192.168.0.0/16.
Cependant, il n'y a pas de moyen multiplateforme d'obtenir toutes les adresses IP. Sous Linux, vous pouvez utiliser l'ioctl SIOCGIFCONF
_.
Un léger raffinement de la version des commandes qui utilise la commande IP et renvoie les adresses IPv4 et IPv6:
import commands,re,socket
#A generator that returns stripped lines of output from "ip address show"
iplines=(line.strip() for line in commands.getoutput("ip address show").split('\n'))
#Turn that into a list of IPv4 and IPv6 address/mask strings
addresses1=reduce(lambda a,v:a+v,(re.findall(r"inet ([\d.]+/\d+)",line)+re.findall(r"inet6 ([\:\da-f]+/\d+)",line) for line in iplines))
#addresses1 now looks like ['127.0.0.1/8', '::1/128', '10.160.114.60/23', 'fe80::1031:3fff:fe00:6dce/64']
#Get a list of IPv4 addresses as (IPstring,subnetsize) tuples
ipv4s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if '.' in addr)]
#ipv4s now looks like [('127.0.0.1', 8), ('10.160.114.60', 23)]
#Get IPv6 addresses
ipv6s=[(ip,int(subnet)) for ip,subnet in (addr.split('/') for addr in addresses1 if ':' in addr)]
Eh bien, vous pouvez utiliser la commande "ip route" sur GNU/Linux pour connaître votre adresse IP actuelle.
Ceci montre l’adresse IP donnée à l’interface par le serveur DHCP fonctionnant sur le routeur/modem. Habituellement, "192.168.1.1/24" est l'adresse IP du réseau local, où "24" correspond à la plage d'adresses IP possibles indiquée par le serveur DHCP dans la plage de masque.
Voici un exemple: Notez que PyNotify est juste un ajout pour que mon point soit clair et n’est pas requis du tout.
#! /usr/bin/env python
import sys , pynotify
if sys.version_info[1] != 7:
raise RuntimeError('Python 2.7 And Above Only')
from subprocess import check_output # Available on Python 2.7+ | N/A
IP = check_output(['ip', 'route'])
Split_Result = IP.split()
# print Split_Result[2] # Remove "#" to enable
pynotify.init("image")
notify = pynotify.Notification("Ip", "Server Running At:" + Split_Result[2] , "/home/User/wireless.png")
notify.show()
L'avantage de cela est qu'il n'est pas nécessaire de spécifier l'interface réseau. C'est très utile lors de l'exécution d'un serveur de socket
Vous pouvez installer PyNotify en utilisant easy_install ou même Pip:
easy_install py-notify
ou
pip install py-notify
ou dans un script/interprète python
from pip import main
main(['install', 'py-notify'])
netifaces est disponible via pip et easy_install. (Je sais, ce n'est pas en base, mais cela pourrait valoir la peine d'être installé.)
netifaces a quelques bizarreries sur toutes les plateformes:
Voici quelques codes de netifaces pour jouer avec:
import netifaces
PROTO = netifaces.AF_INET # We want only IPv4, for now at least
# Get list of network interfaces
# Note: Can't filter for 'lo' here because Windows lacks it.
ifaces = netifaces.interfaces()
# Get all addresses (of all kinds) for each interface
if_addrs = [netifaces.ifaddresses(iface) for iface in ifaces]
# Filter for the desired address type
if_inet_addrs = [addr[PROTO] for addr in if_addrs if PROTO in addr]
iface_addrs = [s['addr'] for a in if_inet_addrs for s in a if 'addr' in s]
# Can filter for '127.0.0.1' here.
Le code ci-dessus ne mappe pas une adresse sur son nom d'interface (utile pour générer des règles ebtables/iptables à la volée). Voici donc une version qui conserve les informations ci-dessus avec le nom de l'interface dans un tuple:
import netifaces
PROTO = netifaces.AF_INET # We want only IPv4, for now at least
# Get list of network interfaces
ifaces = netifaces.interfaces()
# Get addresses for each interface
if_addrs = [(netifaces.ifaddresses(iface), iface) for iface in ifaces]
# Filter for only IPv4 addresses
if_inet_addrs = [(tup[0][PROTO], tup[1]) for tup in if_addrs if PROTO in tup[0]]
iface_addrs = [(s['addr'], tup[1]) for tup in if_inet_addrs for s in tup[0] if 'addr' in s]
Et non, je ne suis pas amoureuse des compréhensions de liste. C'est juste la façon dont mon cerveau fonctionne ces jours-ci.
L'extrait suivant va tout imprimer:
from __future__ import print_function # For 2.x folks
from pprint import pprint as pp
print('\nifaces = ', end='')
pp(ifaces)
print('\nif_addrs = ', end='')
pp(if_addrs)
print('\nif_inet_addrs = ', end='')
pp(if_inet_addrs)
print('\niface_addrs = ', end='')
pp(iface_addrs)
Prendre plaisir!
Note: Ceci n'utilise pas la bibliothèque standard, mais assez simple.
$ pip install pif
from pif import get_public_ip
get_public_ip()
import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)
Cela vous retournera l'adresse IP dans le système Ubuntu ainsi que MacOS. La sortie sera l'adresse IP du système comme mon adresse IP: 192.168.1.10.
Pour obtenir l'adresse IP, vous pouvez utiliser une commande Shell directement dans python :
import socket, subprocess
def getIpAndHostname():
hostname = socket.gethostname()
Shell_cmd = "ifconfig | awk '/inet addr/{print substr($2,6)}'"
proc = subprocess.Popen([Shell_cmd], stdout=subprocess.PIPE, Shell=True)
(out, err) = proc.communicate()
ip_list = out.split('\n')
ip = ip_list[0]
for _ip in ip_list:
try:
if _ip != "127.0.0.1" and _ip.split(".")[3] != "1":
ip = _ip
except:
pass
return ip, hostname
ip_addr, hostname = getIpAndHostname()
import socket
socket.gethostbyname(socket.getfqdn())
Je devais résoudre le problème "Déterminer si une adresse IP est locale ou non", et ma première idée fut de créer une liste d'adresses IP locales, puis de les comparer. C'est ce qui m'a amené à cette question. Cependant, j'ai réalisé par la suite qu'il existait un moyen plus simple de le faire: essayez de vous lier sur cette adresse IP et de voir si cela fonctionne.
_local_ip_cache = []
_nonlocal_ip_cache = []
def ip_islocal(ip):
if ip in _local_ip_cache:
return True
if ip in _nonlocal_ip_cache:
return False
s = socket.socket()
try:
try:
s.bind((ip, 0))
except socket.error, e:
if e.args[0] == errno.EADDRNOTAVAIL:
_nonlocal_ip_cache.append(ip)
return False
else:
raise
finally:
s.close()
_local_ip_cache.append(ip)
return True
Je sais que cela ne répond pas directement à la question, mais cela devrait être utile à quiconque tente de résoudre la question connexe et qui suit le même train de pensées. Cela a l'avantage d'être une solution multi-plateforme (je pense).
Pour obtenir une liste des adresses IP sur les systèmes * nix,
import subprocess
co = subprocess.Popen(['ifconfig'], stdout = subprocess.PIPE)
ifconfig = co.stdout.read()
ip_regex = re.compile('((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-4]|2[0-5][0-9]|[01]?[0-9][0-9]?))')
[match[0] for match in ip_regex.findall(ifconfig, re.MULTILINE)]
Bien qu'il soit un peu tard pour cette réponse, j'ai pensé que quelqu'un d'autre pourrait la trouver utile :-)
PS: Il retournera également les adresses de diffusion et le masque de réseau.
Ce n'est pas très Pythonic, mais cela fonctionne de manière fiable sur Windows.
def getWinIP(version = 'IPv4'):
import subprocess
if version not in ['IPv4', 'IPv6']:
print 'error - protocol version must be "IPv4" or "IPv6"'
return None
ipconfig = subprocess.check_output('ipconfig')
my_ip = []
for line in ipconfig.split('\n'):
if 'Address' in line and version in line:
my_ip.append(line.split(' : ')[1].strip())
return my_ip
print getWinIP()
Oui, c'est un bidouillage, mais parfois, je n'ai pas le goût de deviner un système d'exploitation, et d'aller de l'avant et d'utiliser ce qui est intégré et qui fonctionne.
Une version Python 3.4 utilisant le package asyncio nouvellement introduit.
async get_local_ip():
loop = asyncio.get_event_loop()
transport, protocol = await loop.create_datagram_endpoint(
asyncio.DatagramProtocol,
remote_addr=('8.8.8.8', 80))
result = transport.get_extra_info('sockname')[0])
transport.close()
return result
Ceci est basé sur UnkwnTech excellente réponse .
Si vous recherchez une adresse IPV4 différente de votre adresse IP localhost 127.0.0.1
, voici un bon morceau de codes python:
import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8')
address=address[:-1]
Ce qui peut aussi être écrit en une seule ligne:
address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]
Même si vous mettez localhost
dans /etc/hostname
, le code donnera toujours votre adresse IP locale.
Ok, ceci est donc spécifique à Windows et nécessite l’installation du module python WMI , mais cela semble beaucoup moins compliqué que de constamment essayer d’appeler un serveur externe. C'est juste une autre option, car il y a déjà beaucoup de bonnes, mais cela pourrait être un bon choix pour votre projet.
Import WMI
def getlocalip():
local = wmi.WMI()
for interface in local.Win32_NetworkAdapterConfiguration(IPEnabled=1):
for ip_address in interface.IPAddress:
if ip_address != '0.0.0.0':
localip = ip_address
return localip
>>>getlocalip()
u'xxx.xxx.xxx.xxx'
>>>
Soit dit en passant, WMI est très puissant ... si vous faites l’administration distante de machines Windows, vous devez absolument vérifier ce qu’elle peut faire.
from netifaces import interfaces, ifaddresses, AF_INET
iplist = [ifaddresses(face)[AF_INET][0]["addr"] for face in interfaces() if AF_INET in ifaddresses(face)]
print(iplist)
['10.8.0.2', '192.168.1.10', '127.0.0.1']
Une machine peut avoir plusieurs interfaces réseau (y compris la boucle locale 127.0.0.1) que vous avez mentionnée. En ce qui concerne le système d'exploitation, il s'agit également d'une "adresse IP réelle".
Si vous souhaitez suivre toutes les interfaces, consultez le paquet Puthon suivant: http://alastairs-place.net/netifaces/
Je pense que vous pouvez éviter que gethostbyname renvoie 127.0.0.1 si vous omettez l'entrée en boucle à partir de votre fichier hosts. (à vérifier).
Encore une autre variante des réponses précédentes peut être sauvegardée dans un script exécutable nommé my-ip-to
:
#!/usr/bin/env python
import sys, socket
if len(sys.argv) > 1:
for remote_Host in sys.argv[1:]:
# determine local Host ip by outgoing test to another Host
# use port 9 (discard protocol - RFC 863) over UDP4
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect((remote_Host, 9))
my_ip = s.getsockname()[0]
print(my_ip, flush=True)
else:
import platform
my_name = platform.node()
my_ip = socket.gethostbyname(my_name)
print(my_ip)
il faut un nombre quelconque d’hôtes distants et imprimer des ips locaux pour les atteindre un par un:
$ my-ip-to z.cn g.cn localhost
192.168.11.102
192.168.11.102
127.0.0.1
$
Et imprimez le meilleur pari quand aucun argument n'est donné.
$ my-ip-to
192.168.11.102
Pour Linux, vous pouvez simplement utiliser check_output
de la commande système hostname -I
comme ceci:
from subprocess import check_output
check_output(['hostname', '-I'])
Simple mais doux!
def getip():
import socket
hostname= socket.gethostname()
ip=socket.gethostbyname(hostname)
return(ip)
Ceci est très similaire aux réponses précédemment postées, mais je n’en ai trouvé aucune avec cet usage des appels. C'est ce que j'utilise pour ipv4. Pour ipv6, changez le '.' dans ':' dans
import socket
print next(i[4][0] for i in socket.getaddrinfo(
socket.gethostname(), 80) if '127.' not in i[4][0] and '.' in i[4][0]);"
Pour un env Linux, lisez le fichier/proc/net/tcp, le second (adresse locale) et le troisième (remoteaddress) donneront les adresses IP au format hexa.
Conseil: Si la deuxième colonne est mise à zéro (00000000: 0000), c’est un port d'écoute :)
https://github.com/romol0s/python/blob/master/general/functions/getTcpListenIpsByPort.py
https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt