Lokale IP-Adressen mit Pythons stdlib finden

Lesezeit: 8 Minuten

Benutzer-Avatar
UnkwnTech

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

  • Die lokale IP? Oder öffentliche IP? Wie gehen Sie mit Systemen mit mehreren IPs um?

    – Sargun Dillon

    5. November 2008 um 17:29 Uhr

  • verwenden ifconfig -a und die Ausgabe von dort verwenden …

    – Fredrik Pihl

    23. Juni 2011 um 11:18 Uhr

  • @Fredrik Das ist eine schlechte Idee. Erstens verzweigen Sie unnötigerweise einen neuen Prozess, und das kann Ihr Programm daran hindern, in streng gesperrten Konfigurationen zu arbeiten (oder Sie müssen Rechte zulassen, die Ihr Programm nicht benötigt). Zweitens führen Sie Fehler für Benutzer verschiedener Gebietsschemata ein. Drittens, wenn Wenn Sie sich entscheiden, überhaupt ein neues Programm zu starten, sollten Sie kein veraltetes starten – ip addr ist viel besser geeignet (und einfacher zu parsen, um zu booten).

    – Phihag

    23. Juni 2011 um 13:07 Uhr

  • @phihag du hast absolut recht, danke, dass du meine Dummheit korrigiert hast

    – Fredrik Pihl

    24. Juni 2011 um 20:16 Uhr

  • Ein grundlegenderes Problem besteht hier darin, dass in einem richtig geschriebenen modernen Netzwerkprogramm die richtige(n) lokale(n) IP-Adresse(n) vom Peer oder dem Satz potenzieller Peers abhängt. Wenn die lokale IP-Adresse dazu benötigt wird bind ein Socket zu einer bestimmten Schnittstelle, dann ist dies eine politische Angelegenheit. Wenn die lokale IP-Adresse benötigt wird, um sie an einen Peer zu übergeben, damit der Peer “zurückrufen” kann, dh um eine Verbindung zurück zum lokalen Computer herzustellen, hängt die Situation davon ab, ob NAT (Network Address Translation) vorhanden ist. Kästen dazwischen. Wenn keine NATs vorhanden sind, getsocknameist eine gute Wahl.

    – Pekka Nikander

    30. April 2012 um 4:58 Uhr


Benutzer-Avatar
Vinko Vrsalović

import socket
socket.gethostbyname(socket.gethostname())

Dies wird nicht immer funktionieren (gibt zurück 127.0.0.1 auf Maschinen mit dem Hostnamen in /etc/hosts wie 127.0.0.1), ein Palliativ wäre, was Gimel zeigt, verwenden socket.getfqdn() stattdessen. Natürlich benötigt Ihr Rechner einen auflösbaren Hostnamen.

  • Man sollte beachten, dass dies keine plattformunabhängige Lösung ist. Viele Linuxe geben bei dieser Methode 127.0.0.1 als Ihre IP-Adresse zurück.

    – Jason Baker

    3. Oktober 2008 um 12:07 Uhr

  • Eine Variante: socket.gethostbyname(socket.getfqdn())

    – Gimel

    3. Oktober 2008 um 12:08 Uhr

  • Dies scheint nur eine einzige IP-Adresse zurückzugeben. Was ist, wenn die Maschine mehrere Adressen hat?

    – Jason R. Coombs

    23. Oktober 2009 um 14:39 Uhr

  • Unter Ubuntu gibt dies aus irgendeinem Grund 127.0.1.1 zurück.

    – schlüpft

    20. März 2012 um 5:52 Uhr

  • @Jason R. Coombs, verwenden Sie den folgenden Code, um die Liste der IPv4-Adressen abzurufen, die zum Hostcomputer gehören: socket.gethostbyname_ex(socket.gethostname())[-1]

    – Barmaley

    15. Mai 2015 um 20:36 Uhr


  • Funktioniert in Raspbian mit Python 2 und 3!

    – pierce.jason

    23. September 2015 um 17:03 Uhr

  • Brillant. Funktioniert auf Win7,8,8.1 + Linux Mint & Arch, einschließlich VMs.

    – Schermy

    3. März 2016 um 0:07 Uhr


  • Funktioniert in Windows 10 Pro! Danke, Jamieson Becker!

    – Waldemar

    12. April 2017 um 14:02 Uhr

  • Aus irgendeinem Grund funktioniert dies nicht unter Mac OS X El Capitan 10.11.6 (es generiert einen Ausnahme-Betriebssystemfehler: [Errno 49] Angeforderte Adresse kann nicht zugewiesen werden). Das Ändern des Ports von ‘0’ auf ‘1’: s.connect((‘10.255.255.255’, 1)) hat bei mir sowohl unter Mac OS X als auch unter Linux Ubuntu 17.04 funktioniert

    – Pedro Scarapicchia Junior

    15. April 2017 um 6:36 Uhr


  • Dies sollte die akzeptierte Antwort sein. socket.gethostbyname(socket.gethostname()) liefert schreckliche Ergebnisse.

    – Jason Floyd

    15. Oktober 2018 um 18:19 Uhr

Benutzer-Avatar
Alexander

Als Alias ​​genannt myip:

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 finden.
  • Gibt nicht das richtige Ergebnis für Computer mit mehreren IP-Adressen, IPv6, keiner konfigurierten IP-Adresse oder keinem Internetzugang zurück.
  • Berichten zufolge funktioniert dies nicht mit den neuesten Versionen von macOS.

HINWEIS: Wenn Sie beabsichtigen, so etwas in einem Python-Programm zu verwenden, ist der richtige Weg, ein Python-Modul zu verwenden, das IPv6-Unterstützung hat.


Dasselbe 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])
  • Dies löst eine Ausnahme aus, wenn keine IP-Adresse konfiguriert ist.

Version, die auch in 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:

Verwenden socket.gethostbyname(socket.gethostname()) funktionierte hier nicht, weil einer der Computer, auf denen ich war, einen hatte /etc/hosts mit doppelten Einträgen und Verweisen auf sich selbst. socket.gethostbyname() gibt nur den letzten Eintrag zurück in /etc/hosts.

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

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, behandelt jedoch nicht mehrere Netzwerkgeräte oder IPv6. Bei neueren Linux-Distributionen funktionierte es jedoch nicht mehr, also habe ich stattdessen diese alternative Technik ausprobiert. Es versucht, eine Verbindung zum Google-DNS-Server unter herzustellen 8.8.8.8 am Hafen 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])

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

Mit der zunehmenden Popularität von IPv6 und für Server mit mehreren Netzwerkschnittstellen ist die Verwendung eines Python-Moduls eines Drittanbieters zum Ermitteln der IP-Adresse wahrscheinlich robuster und zuverlässiger als jede der hier aufgeführten Methoden.

  • @Alexander: Ich sage nur, dass diese Antwort viel weniger nützlich ist als früher (und es ist nicht so, als wäre das Herausfiltern von Duplikaten eine große Sache;). Laut Dokumentation socket.getaddrinfo() sollte plattformübergreifend konsistent funktionieren – aber ich habe es nur unter Linux überprüft und mich nicht um andere Betriebssysteme gekümmert.

    – Wladimir Palant

    4. Oktober 2013 um 7:01 Uhr

  • @Alexander, /etc/resolve.conf: No such file or directory und ich habe die lokale IPv4-Adresse von angezeigt ifconfig.

    – anatoly techtonik

    16. Dezember 2013 um 16:30 Uhr

  • Ich kann bestätigen, dass die aktualisierte Version mit Ubuntu 14.04 sowohl mit Python2 als auch mit Py3k funktioniert.

    – Uli Köhler

    6. Juni 2014 um 22:55 Uhr

  • Das “update” zeigt einen netten Trick mit connect() auf einem UDP-Socket. Es sendet keinen Datenverkehr, lässt Sie jedoch herausfinden, was die Absenderadresse für Pakete an den angegebenen Empfänger wäre. Der Port ist wahrscheinlich irrelevant (sogar 0 sollte funktionieren). Auf einem Multihomed-Host ist es wichtig, eine Adresse im richtigen Subnetz auszuwählen.

    – Peter Hansen

    13. Juni 2014 um 21:19 Uhr

  • Der kombinierte Alias-Code initiiert eine unnötige externe Verbindung zu 8.8.8.8, selbst wenn gethostbyname_ex hat eine gültige IP zurückgegeben. Dies wird in LANs vom Typ „Walled Garden“ ohne Internet einbrechen. Der externe Anruf kann mit bedingt gemacht werden orz.B: ips = [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]]

    – ccpizza

    22. Oktober 2017 um 9:47 Uhr

Benutzer-Avatar
ccpizza

Du kannst den … benutzen Netzgesichter Modul. Tipp einfach:

pip install netifaces

in Ihrer Befehlsshell und es installiert sich selbst in der Standard-Python-Installation.

Dann kannst du es so verwenden:

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 druckte es:

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

  • @Alexander: Ich sage nur, dass diese Antwort viel weniger nützlich ist als früher (und es ist nicht so, als wäre das Herausfiltern von Duplikaten eine große Sache;). Laut Dokumentation socket.getaddrinfo() sollte plattformübergreifend konsistent funktionieren – aber ich habe es nur unter Linux überprüft und mich nicht um andere Betriebssysteme gekümmert.

    – Wladimir Palant

    4. Oktober 2013 um 7:01 Uhr

  • @Alexander, /etc/resolve.conf: No such file or directory und ich habe die lokale IPv4-Adresse von angezeigt ifconfig.

    – anatoly techtonik

    16. Dezember 2013 um 16:30 Uhr

  • Ich kann bestätigen, dass die aktualisierte Version mit Ubuntu 14.04 sowohl mit Python2 als auch mit Py3k funktioniert.

    – Uli Köhler

    6. Juni 2014 um 22:55 Uhr

  • Das “update” zeigt einen netten Trick mit connect() auf einem UDP-Socket. Es sendet keinen Datenverkehr, lässt Sie jedoch herausfinden, was die Absenderadresse für Pakete an den angegebenen Empfänger wäre. Der Port ist wahrscheinlich irrelevant (sogar 0 sollte funktionieren). Auf einem Multihomed-Host ist es wichtig, eine Adresse im richtigen Subnetz auszuwählen.

    – Peter Hansen

    13. Juni 2014 um 21:19 Uhr

  • Der kombinierte Alias-Code initiiert eine unnötige externe Verbindung zu 8.8.8.8, selbst wenn gethostbyname_ex hat eine gültige IP zurückgegeben. Dies wird in LANs vom Typ „Walled Garden“ ohne Internet einbrechen. Der externe Anruf kann mit bedingt gemacht werden orz.B: ips = [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]]

    – ccpizza

    22. Oktober 2017 um 9:47 Uhr

Wenn der Computer eine Route zum Internet hat, wird dies der Fall sein stets funktionieren, um die bevorzugte lokale IP-Adresse zu erhalten, 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]

  • Wie funktioniert das ? , 8.8.8.8 ist ein google dns server können wir es mit einem lokalen dns server machen?

    – Ciasto piekarz

    6. April 2020 um 21:22 Uhr

  • @Ciastopiekarz Die Adresse muss nicht gültig sein. Siehe: stackoverflow.com/a/28950776/14280715

    – äh

    29. Dezember 2021 um 12:02 Uhr

1129410cookie-checkLokale IP-Adressen mit Pythons stdlib finden

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy