J'ai plusieurs cartes d'interface réseau sur mon ordinateur, chacune avec sa propre adresse IP.
Lorsque j'utilise gethostbyname(gethostname())
du module socket
de Python (intégré), il n'en renvoie qu'un. Comment puis-je obtenir les autres?
Utilisez le module netifaces
. La mise en réseau étant complexe, utiliser des netifaces peut être un peu délicat, mais voici comment faire ce que vous voulez:
>>> import netifaces
>>> netifaces.interfaces()
['lo', 'eth0']
>>> netifaces.ifaddresses('eth0')
{17: [{'broadcast': 'ff:ff:ff:ff:ff:ff', 'addr': '00:11:2f:32:63:45'}], 2: [{'broadcast': '10.0.0.255', 'netmask': '255.255.255.0', 'addr': '10.0.0.2'}], 10: [{'netmask': 'ffff:ffff:ffff:ffff::', 'addr': 'fe80::211:2fff:fe32:6345%eth0'}]}
>>> for interface in netifaces.interfaces():
... print netifaces.ifaddresses(interface)[netifaces.AF_INET]
...
[{'peer': '127.0.0.1', 'netmask': '255.0.0.0', 'addr': '127.0.0.1'}]
[{'broadcast': '10.0.0.255', 'netmask': '255.255.255.0', 'addr': '10.0.0.2'}]
>>> for interface in netifaces.interfaces():
... for link in netifaces.ifaddresses(interface)[netifaces.AF_INET]:
... print link['addr']
...
127.0.0.1
10.0.0.2
Cela peut être rendu un peu plus lisible comme ceci:
from netifaces import interfaces, ifaddresses, AF_INET
def ip4_addresses():
ip_list = []
for interface in interfaces():
for link in ifaddresses(interface)[AF_INET]:
ip_list.append(link['addr'])
return ip_list
Si vous voulez des adresses IPv6, utilisez AF_INET6
au lieu de AF_INET
. Si vous vous demandez pourquoi netifaces
utilise des listes et des dictionnaires partout, c'est parce qu'un même ordinateur peut avoir plusieurs cartes d'interface réseau et que chaque NIC peut avoir plusieurs adresses et que chaque adresse possède son propre ensemble d'options.
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
Toutes les adresses en une seule ligne à l'aide du module netifaces
:
[netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] for iface in netifaces.interfaces() if netifaces.AF_INET in netifaces.ifaddresses(iface)]
Juste pour être complet, une autre option serait d’utiliser psutil .
import socket
import psutil
def get_ip_addresses(family):
for interface, snics in psutil.net_if_addrs().items():
for snic in snics:
if snic.family == family:
yield (interface, snic.address)
ipv4s = list(get_ip_addresses(socket.AF_INET))
ipv6s = list(get_ip_addresses(socket.AF_INET6))
La fonction dont vous avez besoin est net_if_addrs
. C'est à dire.:
import psutil
psutil.net_if_addrs()
Ce qui donne quelque chose comme ça (Python 3):
{'br-ae4880aa80cf': [snic(family=<AddressFamily.AF_INET: 2>, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'docker0': [snic(family=<AddressFamily.AF_INET: 2>, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'eno1': [snic(family=<AddressFamily.AF_PACKET: 17>, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
'wlp2s0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=<AddressFamily.AF_PACKET: 17>, address='00:21:27:ee:d6:03', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
(Python 2):
{'br-ae4880aa80cf': [snic(family=2, address='172.18.0.1', netmask='255.255.0.0', broadcast='172.18.0.1', ptp=None),
snic(family=17, address='02:42:e5:ae:39:94', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'docker0': [snic(family=2, address='172.17.0.1', netmask='255.255.0.0', broadcast='172.17.0.1', ptp=None),
snic(family=17, address='02:42:38:d2:4d:77', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'eno1': [snic(family=17, address='54:be:f7:0b:cf:a9', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)],
'lo': [snic(family=2, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None),
snic(family=17, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)],
'wlp2s0': [snic(family=2, address='192.168.1.4', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None),
snic(family=17, address='00:21:27:ee:d6:03', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}
Note : Etant donné que vous pouvez avoir plus d'une adresse de la même famille associée à chaque interface, les valeurs dict sont des listes.
Chaque snic
est un namedtuple
qui comprend 5 champs:
family
: la famille d'adresses, soit AF_INET, AF_INET6 ou psutil.AF_LINK, qui fait référence à une adresse MAC.address
: l'adresse principale NIC (toujours définie).netmask
: l'adresse du masque de réseau (peut être None).broadcast
: l'adresse de diffusion (peut être Aucun).ptp
: signifie “point à point”; c'est l'adresse de destination sur une interface point à point (généralement un VPN). broadcast et ptp s’excluent mutuellement (peut être None).https://docs.python.org/3.4/library/socket.html#socket.if_nameindex
socket.if_nameindex ()
Renvoie une liste de tuples d'informations d'interface réseau (index int, name string). OSError si l'appel système échoue.
Disponibilité: Unix.
Nouveau dans la version 3.3.
fait ce code qui est exécutable sur Python 3.4, UNIX/Linux
#!/env/python3.4
import socket
import fcntl
import struct
def active_nic_addresses():
"""
Return a list of IPv4 addresses that are active on the computer.
"""
addresses = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1]
return addresses
def get_ip_address( NICname ):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(
s.fileno(),
0x8915, # SIOCGIFADDR
struct.pack('256s', NICname[:15].encode("UTF-8"))
)[20:24])
def nic_info():
"""
Return a list with tuples containing NIC and IPv4
"""
nic = []
for ix in socket.if_nameindex():
name = ix[1]
ip = get_ip_address( name )
nic.append( (name, ip) )
return nic
if __== "__main__":
print( active_nic_addresses() )
print( nic_info() )
Imprimera quelque chose comme:
['192.168.0.2']
[('lo', '127.0.0.1'), ('enp3s0', '192.168.0.2')]
Voici une routine pour rechercher toutes les interfaces IPv4 et IPv6. Comme l'a déjà souligné un autre poster, socket.gethostbyname_ex () ne fonctionne pas pour IPv6 et la documentation Python recommande une utilisation socket.getaddressinfo () .
Cette routine ajoute l'interface de rappel IPv4 (127.0.0.1). S'il existe des interfaces IPv6, elle ajoute également l'interface de rappel IPv6 (:: 1). Socket.getaddrinfo () me donnera un ou les deux, mais seulement si je n'ai pas d'autre interface disponible.
Pour mes besoins, je voulais essayer d'ouvrir un socket UDP sur un port spécifié de chacune de mes interfaces disponibles. C'est pourquoi le code contient "port" et socket.SOCK_DGRAM. Il est prudent de changer ceux-ci, par exemple si vous n'avez pas de port en tête.
addrinfo_ipv4 = socket.getaddrinfo(hostname,port,socket.AF_INET,socket.SOCK_DGRAM)
addrinfo_ipv6 = []
try:
addrinfo_ipv6 = socket.getaddrinfo(hostname,port,socket.AF_INET6,socket.SOCK_DGRAM)
except socket.gaierror:
pass
addrinfo = [(f,t,a) for f,t,p,cn,a in addrinfo_ipv4+addrinfo_ipv6]
addrinfo_local = [(socket.AF_INET,socket.SOCK_DGRAM,('127.0.0.1',port))]
if addrinfo_ipv6:
addrinfo_local.append( (socket.AF_INET6,socket.SOCK_DGRAM,('::1',port)) )
[addrinfo.append(ai) for ai in addrinfo_local if ai not in addrinfo]
C'est linux seulement, mais il y a une recette très simple ici http://code.activestate.com/recipes/439094/
Il utilise probablement un code similaire au paquet netifaces mentionné dans une autre réponse (mais la version actuelle est liée ici)
Socket.getaddrinfo () ne renvoie pas l'adresse IP associée au périphérique. Si votre fichier hosts contient une ligne avec "127.0.1.1 yourhost.example.com yourhost", qui est une configuration courante, getaddrinfo ne renverra que 127.0.1.1.
Cet extrait donnera une liste de toutes les adresses IPV4 disponibles dans le système.
import itertools
from netifaces import interfaces, ifaddresses, AF_INET
links = filter(None, (ifaddresses(x).get(AF_INET) for x in interfaces()))
links = itertools.chain(*links)
ip_addresses = [x['addr'] for x in links]
Vous pouvez le faire assez facilement comme ceci:
import netifaces
for interface in netifaces.interfaces():
print netifaces.ifaddresses(interface)
Pour plus d'informations, vous pouvez consulter la documentation netifaces .
Comme ce fil l'indique, il existe de nombreuses façons d'obtenir le même résultat. Je suggère d'utiliser le filtre de famille intégré dans getaddrinfo()
et d'analyser le tuple standardisé comme suit:
from socket import getaddrinfo, AF_INET, gethostname
for ip in getaddrinfo(Host=gethostname(), port=None, family=AF_INET):
print(ip[4][0])
Exemple de sortie:
192.168.55.1
192.168.170.234
Je pense que la réponse de @Harley Holcombe est réalisable, mais si vous avez des cartes réseau virtuelles sans adresse IP, cela entraînera une erreur. c'est donc j'ai modifié:
def get_lan_ip():
for interface in interfaces():
try:
for link in ifaddresses(interface)[AF_INET]:
if str(link['addr']).startswith("172."):
return str(link['addr'])
except:
pass
cela ne fera que retourner votre lan ipv4
Vous devez obtenir directement toutes les adresses IP configurées IP, par exemple en exécutant ifconfig et en analysant sa sortie (il est également possible de faire ce que ifconfig fait directement dans Python , voir comment cela se fait dans C ). Si vous voulez des noms d'hôte, utilisez gethostbyaddr.