Frage

Ich habe von mehreren Netzwerk-Interface-Karten auf meinem computer, jeder mit seiner eigenen IP-Adresse.

Wenn ich benutze gethostbyname(gethostname()) von Python (built-in) socket Modul, es wird nur einer von Ihnen.Wie bekomme ich die anderen?

War es hilfreich?

Lösung

Mit dem netifaces Modul. Da Vernetzung komplexer, netifaces verwendet, kann ein wenig schwierig sein, aber hier ist, wie zu tun, was Sie wollen:

>>> 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

Dies kann ein wenig besser lesbar wie folgt vorgenommen werden:

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

Wenn Sie IPv6-Adressen möchten, verwenden Sie AF_INET6 statt AF_INET. Wenn Sie sich fragen, warum netifaces Listen und Wörterbücher verwenden alle über den Platz, es ist, weil ein einzelner Computer mehr Netzwerkkarten haben kann, und jeder NIC kann mehrere Adressen hat, und jede Adresse hat seine eigene Reihe von Optionen.

Andere Tipps

import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

Alle Adressen in einer Zeile mit Hilfe des netifaces Modul:

[netifaces.ifaddresses(iface)[netifaces.AF_INET][0]['addr'] for iface in netifaces.interfaces() if netifaces.AF_INET in netifaces.ifaddresses(iface)]

Nur der Vollständigkeit halber, eine andere Möglichkeit wäre die Verwendung von psutil.

tldr;

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))

Erklärung

Die Funktion, die Sie brauchen, ist net_if_addrs.I. e.:

import psutil
psutil.net_if_addrs()

Die Ergebnisse in so etwas wie dieser (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)]}

Hinweis:Da kann man mehr als eine Adresse, die der gleichen Familie, die jeder Schnittstelle, die dict-Werte-Listen.

Jeder snic ist ein namedtuple die enthält 5 Felder:

  • family:die Adressfamilie AF_INET, AF_INET6 oder psutil.AF_LINK, die sich auf eine MAC-Adresse.
  • address:die primäre NIC-Adresse (immer setzen).
  • netmask:die netmask-Adresse (vielleicht Keine).
  • broadcast:die broadcast-Adresse (vielleicht Keine).
  • ptp:steht für "Punkt zu Punkt";es ist die Ziel-Adresse auf einem Punkt-zu-Punkt-Schnittstelle (in der Regel ein VPN).broadcast-und ptp schließen sich gegenseitig aus (vielleicht Keine).

https://docs.python.org/3.4/library/ socket.html # socket.if_nameindex

socket.if_nameindex ()

Gibt eine Liste von Netzwerkschnittstelleninformationen (Index int, name string) Tupel. OSError wenn der Systemaufruf fehlschlägt.

Verfügbarkeit:. Unix

Neu in der Version 3.3.


Mit diesem Code gemacht, die auf Python 3.4, UNIX / Linux

fahrbare ist
#!/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 __name__ == "__main__":

    print( active_nic_addresses() )
    print( nic_info() )

Wird so etwas wie Druck:

['192.168.0.2']
[('lo', '127.0.0.1'), ('enp3s0', '192.168.0.2')]

Es ist nur Linux, aber es ist ein sehr einfaches Rezept hier http://code.activestate.com / Rezepte / 439094 /

Es nutzt wahrscheinlich einen ähnlichen Code zum netifaces Paket in einer anderen Antwort erwähnt (aber Strom Version verknüpft hier)

Die socket.getaddrinfo () kehrt nicht tatsächlich die gebundene IP-Adresse für das Gerät. Wenn Ihre Hosts-Datei enthält eine Zeile mit „127.0.1.1 yourhost.example.com IhrHost“, die eine gemeinsame Konfiguration ist, Getaddrinfo nur 127.0.1.1 zurückkehren wird.

Hier ist eine Routine für die Suche nach all IPv4- und IPv6-Schnittstellen. Als vorher bereits erwähnt, socket.gethostbyname_ex () funktioniert nicht für IPv6 und die Python-Dokumentation empfiehlt eine socket.getaddressinfo () statt.

Diese Routine fügt die Callback-IPv4-Schnittstelle (127.0.0.1), und wenn es keine IPv6-Schnittstellen ist dann auch den Rückruf IPv6-Schnittstelle ergänzt (:: 1). Auf meinem Rechner socket.getaddrinfo () gibt mir eine oder beide von diesen aber nur, wenn ich keine anderen Schnittstellen zur Verfügung haben.

Für meine Bedürfnisse, ich wollte auf jeden meiner verfügbaren Schnittstellen einen UDP-Socket auf einem bestimmten Port zu öffnen, um zu versuchen, weshalb der Code „Port“ und socket.SOCK_DGRAM darin. Es ist sicher, diejenigen zu ändern, z.B. wenn Sie nicht über einen Hafen im Sinne haben.

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]

Dieser Code-Schnipsel zeigt eine Liste aller verfügbaren IPv4-Adressen im System geben.

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]

Sie sollten alle IP konfigurierten IP-Adressen direkt erhalten, z.B. von ifconfig laufen und dessen Ausgang das Parsen (es ist auch möglich, zu tun, was ifconfig direkt in Python tut zu sehen, wie es in C erfolgt). Wenn Sie Host-Namen möchten, verwenden gethostbyaddr.

Sie können es ziemlich leicht wie folgt aus:

import netifaces

for interface in netifaces.interfaces():
    print netifaces.ifaddresses(interface)

Für weitere Informationen können Sie die netifaces Dokumentation nachschlagen.

ich glaube, @Harley Holcombe Antwort praktikabel ist, aber wenn Sie einige virtuelle NICs ohne ip haben es Fehler. so ist dies i geändert:

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

Dies wird nur zurückkehren Ihre lan ipv4

Da dieser Thread gibt, gibt es viele Möglichkeiten, um das gleiche Ergebnis acchive, meine vorgeschlagene Art und Weise ist die Bildung in der Familie Filter in getaddrinfo() zu nutzen und das standardisierte Tupel analysiert wie folgt:

from socket import getaddrinfo, AF_INET, gethostname

for ip in getaddrinfo(host=gethostname(), port=None, family=AF_INET):   
    print(ip[4][0])

Beispiel Ausgabe:

192.168.55.1
192.168.170.234
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top