it-swarm.com.de

Lokale IP-Adressen mithilfe der Python stdlib suchen

Wie kann ich lokale IP-Adressen (d. H. 192.168.x.x oder 10.0.x.x) in Python-Plattform unabhängig voneinander und nur mit der Standardbibliothek finden?

456
UnkwnTech
import socket
socket.gethostbyname(socket.gethostname())

Dies funktioniert nicht immer (gibt 127.0.0.1 auf Rechnern zurück, die den Hostnamen in /etc/hosts als 127.0.0.1 haben). Eine Paliative wäre, was Gimel zeigt, stattdessen socket.getfqdn(). Natürlich benötigt Ihr Rechner einen auflösbaren Hostnamen.

374
Vinko Vrsalovic

Ich habe das gerade gefunden, aber es scheint ein bisschen hackig zu sein, aber sie sagen, es auf * nix probiert zu haben und ich habe es unter Windows gemacht und es hat funktioniert.

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()

Dies setzt voraus, dass Sie über einen Internetzugang verfügen und kein lokaler Proxy vorhanden ist.

389
UnkwnTech

Als Alias ​​mit dem Namen myip sollte das überall funktionieren:

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])'"
  • Funktioniert korrekt mit Python 2.x, Python 3.x, modernen und alten Linux-Distributionen, OSX/macOS und Windows, um die aktuelle IPv4-Adresse zu ermitteln.
  • Gibt nicht das korrekte Ergebnis für Maschinen mit mehreren IP-Adressen, IPv6, keiner konfigurierten IP-Adresse oder keinem Internetzugang zurück.

Wie oben, aber nur der Python-Code:

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])
  • Wenn keine IP-Adresse konfiguriert ist, wird eine Ausnahme ausgelöst.

Version, die auch auf LANs ohne Internetverbindung funktioniert:

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

(Danke @ccpizza )


Hintergrund:

Die Verwendung von socket.gethostbyname(socket.gethostname()) hat hier nicht funktioniert, da einer der Computer, auf denen ich mich befand, einen /etc/hosts mit doppelten Einträgen und Verweisen auf sich selbst hatte. socket.gethostbyname() gibt nur den letzten Eintrag in /etc/hosts zurück.

Dies war mein erster Versuch, alle Adressen beginnend mit "127." auszusondern:

import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])

Dies funktioniert mit Python 2 und 3 unter Linux und Windows, jedoch nicht mit mehreren Netzwerkgeräten oder IPv6. Bei den letzten Linux-Distributionen funktionierte das Programm jedoch nicht mehr, weshalb ich stattdessen diese alternative Technik ausprobierte. Es versucht, eine Verbindung zum Google DNS-Server unter 8.8.8.8 am Port 53 herzustellen:

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

Dann kombinierte ich die beiden oben genannten Techniken zu einem Einzeiler, der überall funktionieren sollte, und erstellte den Alias ​​myip und das Python-Snippet oben in dieser Antwort.

Mit der zunehmenden Verbreitung von IPv6 und Servern mit mehreren Netzwerkschnittstellen ist die Verwendung eines Python-Moduls von Drittanbietern zum Ermitteln der IP-Adresse wahrscheinlich robuster und zuverlässiger als die hier aufgelisteten Methoden.

135
Alexander

Diese Methode gibt die "primäre" IP-Adresse in der lokalen Box (derjenigen mit einer Standardroute) zurück.

  • Benötigt KEIN routingfähigen Netzzugang oder irgendeine Verbindung.
  • Funktioniert auch, wenn alle Schnittstellen vom Netzwerk getrennt sind.
  • Benötigt oder versucht nicht, anderswo zu bekommen.
  • Funktioniert mit NAT, öffentlichen, privaten, externen und internen IPs
  • Pure Python 2 (oder 3) ohne externe Abhängigkeiten.
  • Funktioniert unter Linux, Windows und OSX.

Python 2 oder 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

Dies gibt eine einzige IP zurück, die die primäre ist (die mit einer Standardroute). Benötigen Sie stattdessen alle IP-Adressen, die an alle Schnittstellen (einschließlich localhost usw.) angeschlossen sind, finden Sie weitere Informationen unter dieser Antwort .

Wenn Sie sich hinter einer NAT -Firewall wie Ihrer WLAN-Box zu Hause befinden, wird hier nicht Ihre öffentliche NAT IP angezeigt, sondern Ihre private NAT IP im lokalen Netzwerk, das einen Standardwert hat Route zu Ihrem lokalen WLAN-Router; Um die externe IP-Adresse Ihres WLAN-Routers zu erhalten, müssen Sie diese entweder in DIESER Box ausführen oder eine Verbindung zu einem externen Dienst wie whatismyip.com/whatismyipaddress.com herstellen, der die IP-Adresse widerspiegeln könnte. :)

Connect () - Aufruf gemäß den Vorschlägen von Pedro in Kommentaren aktualisiert. (Wenn Sie eine bestimmte Lizenzerklärung benötigen, ist dies gemeinfrei/frei für jegliche Verwendung oder die MIT/CC2-BY-SA-Lizenz pro Stack Overflow-Code/-Inhalt nach Ihrer Wahl.)

134
Jamieson Becker

Sie können das Modul netifaces verwenden. Schreib einfach:

pip install netifaces

in Ihrem Befehl Shell und es wird bei der Standardinstallation von Python installiert.

Dann kannst du es so benutzen:

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

Auf meinem Computer wurde gedruckt:

{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 
 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207

Der Autor dieses Moduls behauptet, dass es unter Windows, UNIX und Mac OS X funktionieren sollte.

82
DzinX

Socket-API-Methode

siehe https://stackoverflow.com/a/28950776/711085

Nachteile:

  • Nicht plattformübergreifend.
  • Erfordert mehr Fallback-Code, der an das Vorhandensein bestimmter Adressen im Internet gebunden ist
  • Dies funktioniert auch nicht, wenn Sie sich hinter einem NAT befinden
  • Erstellt wahrscheinlich eine UDP-Verbindung, die nicht unabhängig von (normalerweise ISP) DNS-Verfügbarkeit ist (siehe andere Antworten für Ideen wie 8.8.8.8: Googles (zufällig auch DNS) -Server)
  • Stellen Sie sicher, dass Sie die Zieladresse UNREACHABLE festlegen, z. B. eine numerische IP-Adresse, deren Einhaltung garantiert ist, dass sie nicht verwendet wird. Verwenden Sie KEINE Domain wie fakesubdomain.google.com oder somefakewebsite.com. Sie werden diese Partei (jetzt oder in der Zukunft) immer noch spammen und dabei auch Ihre eigenen Netzwerkboxen spammen.

Reflektormethode

(Beachten Sie, dass dies nicht die Frage des OP nach der lokalen IP-Adresse beantwortet, z. B. 192.168 ...; es gibt Ihnen Ihre öffentliche IP-Adresse, die je nach Anwendungsfall wünschenswerter sein kann.)

Sie können einige Websites wie whatismyip.com abfragen (jedoch mit einer API), z.

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)

oder wenn Sie Python2 verwenden:

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)

Vorteile:

  • Ein Vorteil dieser Methode ist die plattformübergreifende Methode
  • Es funktioniert hinter hässlichen NATs (z. B. Ihrem Heimrouter).

Nachteile (und Problemumgehungen):

  • Erfordert, dass diese Website aktiv ist, das Format nicht geändert wird (fast sicher nicht) und Ihre DNS-Server funktionieren. Dieses Problem kann durch Abfragen anderer IP-Adressreflektoren von Drittanbietern im Fehlerfall verringert werden.
  • Möglicher Angriffsvektor, wenn Sie nicht mehrere Reflektoren abfragen (um zu verhindern, dass ein angegriffener Reflektor Ihnen sagt, dass Ihre Adresse etwas ist, was er nicht ist) oder wenn Sie kein HTTPS verwenden (um zu verhindern, dass ein Man-in-the-Middle-Angriff vorgibt der Server sein)

edit: Obwohl ich anfangs dachte, dass diese Methoden wirklich schlecht sind (wenn Sie nicht viele Fallbacks verwenden, ist der Code in vielen Jahren möglicherweise irrelevant), stellt sich jedoch die Frage "Was ist das Internet?". Ein Computer kann über viele Schnittstellen verfügen, die auf viele verschiedene Netzwerke verweisen. Um eine genauere Beschreibung des Themas zu erhalten, google nach gateways and routes. Ein Computer kann möglicherweise über ein internes Gateway auf ein internes Netzwerk zugreifen, oder über ein Gateway, das beispielsweise über einen Router auf das World Wide Web zugreift (normalerweise der Fall). Die lokale IP-Adresse, nach der das OP fragt, ist nur in Bezug auf eine einzelne Verbindungsschicht genau definiert. Sie müssen dies also angeben ("ist es die Netzwerkkarte oder das Ethernet-Kabel, über die wir sprechen?") . Es kann mehrere nicht eindeutige Antworten auf diese Frage geben, wenn sie gestellt werden. Die globale IP-Adresse im World Wide Web ist jedoch wahrscheinlich genau definiert (wenn keine massive Fragmentierung des Netzwerks vorliegt): wahrscheinlich der Rückweg über das Gateway, das auf die TLDs zugreifen kann.

48
ninjagecko

Wenn der Computer eine Route zum Internet hat, wird always die bevorzugte lokale IP-Adresse abgerufen, auch wenn/etc/hosts nicht richtig eingestellt ist.

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]
40
Collin Anderson

Unter 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'
>>> 
38
tMC

ich verwende folgendes Modul:

#!/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

Getestet mit Windows und Linux (und erfordert keine zusätzlichen Module), die für die Verwendung auf Systemen vorgesehen sind, die sich in einem einzigen IPv4-basierten LAN befinden.

Die feste Liste der Schnittstellennamen funktioniert nicht für aktuelle Linux-Versionen, die die Änderung von systemd v197 bezüglich vorhersagbarer Schnittstellennamen übernommen haben, wie von Alexander ..__ angegeben die Schnittstellennamen auf Ihrem System oder verwenden Sie eine andere Lösung wie netifaces .

26
smerlin

Ich verwende das auf meinen Ubuntu-Maschinen:

import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]

Das geht nicht.

24
shino

Wenn Sie keine externen Pakete verwenden möchten und sich nicht auf externe Internetserver verlassen möchten, kann dies hilfreich sein. Es ist ein Codebeispiel, das ich unter Google Code Search gefunden und geändert habe, um die erforderlichen Informationen zurückzugeben:

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

Verwendungszweck:

>>> for addr in getIPAddresses():
>>>    print addr
192.168.0.100
10.5.9.207

Da es auf windll angewiesen ist, funktioniert dies nur unter Windows.

19
DzinX

Eine Version, von der ich glaube, dass sie noch nicht veröffentlicht wurde. Ich habe mit Python 2.7 auf Ubuntu 12.04 getestet.

Diese Lösung wurde unter folgender Adresse gefunden: 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])

Beispiel Ergebnis:

>>> get_ip_address('eth0')
'38.113.228.130'
17
Graham Chap

Auf Debian (getestet) und ich vermute die meisten Linux ..

import commands

RetMyIP = commands.getoutput("hostname -I")

Unter MS Windows (getestet) 

import socket

socket.gethostbyname(socket.gethostname())
16
www-0av-Com

Variation über die Antwort von Ninjagecko. Dies sollte in jedem LAN funktionieren, das UDP-Broadcast zulässt, und erfordert keinen Zugriff auf eine Adresse im LAN oder 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())
9
dlm

Eine einfache Möglichkeit, "saubere" Ausgaben über Befehlszeilenprogramme zu erzeugen:

import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
                         "awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips

Es werden alle IPv4-Adressen im System angezeigt.

8
viker

Ich befürchte, es gibt keine guten plattformunabhängigen Möglichkeiten, dies zu tun, außer sich mit einem anderen Computer zu verbinden und sich Ihre IP-Adresse senden zu lassen. Zum Beispiel: findmyipaddress . Beachten Sie, dass dies nicht funktioniert, wenn Sie eine IP-Adresse hinter NAT benötigen, es sei denn, der Computer, zu dem Sie eine Verbindung herstellen, befindet sich ebenfalls hinter NAT.

Hier ist eine Lösung, die unter Linux funktioniert: Ruft die IP-Adresse einer Netzwerkschnittstelle ab .

8
Jason Baker

Dies ist eine Variante der Antwort von UnkwnTech - sie bietet eine get_local_addr()-Funktion, die die primäre LAN-IP-Adresse des Hosts zurückgibt. Ich poste es, weil dies eine Reihe von Dingen hinzufügt: ipv6-Unterstützung, Fehlerbehandlung, Ignorieren von localhost/linklocal-addrs und ein TESTNET-addr (rfc5737) zum Herstellen einer Verbindung.

# 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
7
Eli Collins

Zu Ihrer Information kann ich die Methode überprüfen:

import socket
addr = socket.gethostbyname(socket.gethostname())

Funktioniert in OS X (10.6, 10.5), Windows XP und auf einem gut verwalteten RHEL-Abteilungsserver. Es funktionierte nicht auf einem sehr minimalen CentOS VM, mit dem ich gerade Kernel-Hacking mache. Für diese Instanz können Sie also einfach nach einer 127.0.0.1-Adresse suchen und in diesem Fall Folgendes tun:

if addr == "127.0.0.1":
     import commands
     output = commands.getoutput("/sbin/ifconfig")
     addr = parseaddress(output)

Und dann die IP-Adresse von der Ausgabe parsen. Es ist zu beachten, dass ifconfig standardmäßig nicht im Pfad eines normalen Benutzers enthalten ist. Aus diesem Grund gebe ich den vollständigen Pfad im Befehl an. Ich hoffe das hilft.

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

Dies funktioniert auf den meisten Linux-Boxen:

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()
6
fccoelho

Diese Antwort ist mein persönlicher Versuch, das Problem der LAN-IP zu lösen, da socket.gethostbyname(socket.gethostname()) auch 127.0.0.1 zurückgegeben hat. Diese Methode erfordert keine Internetverbindung, sondern nur eine LAN-Verbindung. Code ist für Python 3.x, könnte aber leicht für 2.x konvertiert werden. UDP Broadcast verwenden:

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())
5
WolfRage

127.0.1.1ist Ihre tatsächliche IP-Adresse. Im Allgemeinen kann ein Computer eine beliebige Anzahl von IP-Adressen haben. Sie können sie nach privaten Netzwerken filtern - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 und 192.168.0.0/16.

Es gibt jedoch keinen plattformübergreifenden Weg, um alle IP-Adressen abzurufen. Unter Linux können Sie die SIOCGIFCONF ioctl verwenden.

4
phihag

Eine leichte Verfeinerung der Befehlsversion, die den IP-Befehl verwendet und IPv4- und IPv6-Adressen zurückgibt:

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)]
4
Ben Last

Nun, Sie können den Befehl "ip route" unter GNU/Linux verwenden, um Ihre aktuelle IP-Adresse zu kennen.

Dies zeigt die IP-Adresse, die der DHCP-Server auf dem Router/Modem an die Schnittstelle gibt. Normalerweise ist "192.168.1.1/24" die IP für das lokale Netzwerk, wobei "24" den Bereich der möglichen IP-Adressen bezeichnet, die vom DHCP-Server innerhalb des Maskenbereichs angegeben werden.

Hier ein Beispiel: Beachten Sie, dass PyNotify nur eine Ergänzung ist, um meinen Punkt klarer zu machen und überhaupt nicht erforderlich ist

#! /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()    

Dies hat den Vorteil, dass Sie die Netzwerkschnittstelle nicht angeben müssen. Das ist sehr nützlich, wenn ein Socket-Server ausgeführt wird

Sie können PyNotify mit easy_install oder sogar Pip installieren:

easy_install py-notify

oder

pip install py-notify

oder innerhalb eines Python-Skripts/Interpreters

from pip import main

main(['install', 'py-notify'])
4
DarkXDroid

netifaces ist über pip und easy_install verfügbar. (Ich weiß, es ist nicht in der Basis, aber es lohnt sich die Installation.)

netifaces hat einige seltsame Eigenschaften auf Plattformen:

  • Die Schnittstelle localhost/loop-back ist möglicherweise nicht immer enthalten (Cygwin).
  • Adressen werden pro Protokoll (z. B. IPv4, IPv6) und Protokolle pro Schnittstelle aufgelistet. Auf einigen Systemen (Linux) hat jedes Protokoll-Schnittstellen-Paar eine eigene Schnittstelle (unter Verwendung der Schnittstellenname: n-Notation), während auf anderen Systemen (Windows) eine einzelne Schnittstelle eine Liste von Adressen für jedes Protokoll hat. In beiden Fällen gibt es eine Protokollliste, die jedoch nur ein einzelnes Element enthalten kann.

Hier ist ein paar Netifaces-Codes zum Spielen:

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.

Der obige Code ordnet eine Adresse nicht ihrem Schnittstellennamen zu (nützlich zum Erzeugen von ebtables/iptables-Regeln im laufenden Betrieb). Also hier eine Version, die die oben genannten Informationen mit dem Schnittstellennamen in einem Tuple enthält:

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]

Und nein, ich bin nicht in Listenverständnisse verliebt. Es ist genau so, wie mein Gehirn heutzutage funktioniert.

Das folgende Snippet druckt alles aus:

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)

Genießen!

3
user3712955

Hinweis: Dies ist nicht die Standardbibliothek, sondern recht einfach.

$ pip install pif

from pif import get_public_ip
get_public_ip()
3
import netifaces as ni 

ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)

Dies gibt Ihnen die IP-Adresse im Ubuntu-System sowie MacOS zurück. Die Ausgabe ist die IP-Adresse des Systems wie meine IP-Adresse: 192.168.1.10.

3
Ishwarya

Um die IP-Adresse zu erhalten, können Sie einen Shell-Befehl direkt in python verwenden:

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()
3
RiccardoCh
import socket
socket.gethostbyname(socket.getfqdn())
2
Oink

Ich musste das Problem lösen "Herausfinden, ob eine IP-Adresse lokal ist oder nicht", und mein erster Gedanke war, eine Liste von IPs zu erstellen, die lokal waren und dann mit ihr übereinstimmen. Das hat mich zu dieser Frage geführt. Später wurde mir jedoch klar, dass es eine einfachere Methode gibt: Versuchen Sie, die IP-Adresse zu binden und zu überprüfen, ob sie funktioniert.

_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

Ich weiß, dass dies die Frage nicht direkt beantwortet, aber dies sollte für jeden hilfreich sein, der versucht, die verwandte Frage zu lösen, und wer demselben Gedankengang folgte. Dies hat den Vorteil einer plattformübergreifenden Lösung (denke ich).

2
Etienne Perot

Eine Liste der IP-Adressen auf * nix-Systemen finden Sie

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

Obwohl es für diese Antwort etwas spät ist, dachte ich, jemand anderes könnte es nützlich finden :-)

PS: Broadcast-Adressen und Netzmaske werden ebenfalls zurückgegeben.

1
Kulbir Saini

Dies ist nicht sehr Pythonic, funktioniert aber zuverlässig unter 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()

Ja, es ist ein Hack, aber manchmal fühle ich mich nicht so, als würde ich ein Betriebssystem neu erraten, und mach einfach weiter und nutze das, was eingebaut ist und funktioniert.

1
LRund

Eine Python 3.4-Version mit dem neu eingeführten Paket asyncio.

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

Dies basiert auf der exzellenten Antwort von UnkwnTech .

1
Frederik Aalund

Wenn Sie nach einer IPV4-Adresse suchen, die sich von Ihrer localhost-IP-Adresse 127.0.0.1 unterscheidet, finden Sie hier ein nettes Stück Python-Codes:

import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8') 
address=address[:-1]

Was kann auch in einer einzigen Zeile geschrieben werden:

address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]

Selbst wenn Sie localhost in /etc/hostname eingeben, wird der Code immer noch Ihre lokale IP-Adresse angeben.

1
hmofrad

Ok, das ist Windows-spezifisch und erfordert die Installation des python WMI-Moduls , aber es scheint weniger hackhaft zu sein, als ständig einen externen Server aufzurufen. Es ist nur eine weitere Option, da es bereits viele gute gibt, aber es könnte für Ihr Projekt gut passen.

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

Übrigens, WMI ist sehr leistungsfähig. Wenn Sie Remote-Administratoren von Fenstermaschinen ausführen, sollten Sie auf jeden Fall prüfen, was es kann.

1
snakebarber
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']
0
Villiam

Ein Rechner kann mehrere Netzwerkschnittstellen (einschließlich des von Ihnen erwähnten lokalen Loopback 127.0.0.1) haben. Für das Betriebssystem ist es auch eine "echte IP-Adresse". 

Wenn Sie alle Schnittstellen nachverfolgen möchten, schauen Sie sich das folgende Puthon-Paket an: http://alastairs-place.net/netifaces/

Ich denke, Sie können vermeiden, dass gethostbyname 127.0.0.1 zurückgibt, wenn Sie den loopback-Eintrag von Ihrer hosts-Datei auslassen. (muss bestätigt werden).

0
ddewaele

Eine weitere Variante zu früheren Antworten kann in einem ausführbaren Skript mit dem Namen my-ip-to gespeichert werden:

#!/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)

es sind beliebig viele Remote-Hosts erforderlich, und es werden lokale IP-Adressen gedruckt, um sie einzeln zu erreichen:

$ my-ip-to z.cn g.cn localhost
192.168.11.102
192.168.11.102
127.0.0.1
$

Und drucken Sie am besten, wenn kein Argument angegeben ist.

$ my-ip-to
192.168.11.102
0
Compl Yue

Unter Linux können Sie einfach check_output des Systembefehls hostname -I wie folgt verwenden:

from subprocess import check_output
check_output(['hostname', '-I'])

Einfach aber süß!

def getip():

    import socket
    hostname= socket.gethostname()
    ip=socket.gethostbyname(hostname)

    return(ip)
0
Matt

Dies ist den zuvor veröffentlichten Antworten sehr ähnlich, aber ich konnte mit dieser Verwendung von Anrufen keine finden. Das ist was ich für ipv4 verwende. Für ipv6 ändern Sie das '.' in zu ':' in 

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]);"
0
Wyrmwood

Für eine Linux-Umgebung lesen Sie/proc/net/tcp, die zweite (lokale Adresse) und dritte (Remoteadresse) geben die IPs im Hexa-Format an.

Tipp: Wenn die zweite Spalte auf Null gesetzt ist (00000000: 0000), ist dies ein Listen Port :)

https://github.com/romol0s/python/blob/master/general/functions/getTcpListenIpsByPort.py

https://www.kernel.org/doc/Documentation/networking/proc_net_tcp.txt

0
Romolo