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?
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.
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.
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])'"
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])
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.
Diese Methode gibt die "primäre" IP-Adresse in der lokalen Box (derjenigen mit einer Standardroute) zurück.
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.)
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.
Socket-API-Methode
siehe https://stackoverflow.com/a/28950776/711085
Nachteile:
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:
Nachteile (und Problemumgehungen):
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.
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]
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'
>>>
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 .
Ich verwende das auf meinen Ubuntu-Maschinen:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
Das geht nicht.
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.
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'
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())
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())
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.
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 .
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
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.
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
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()
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())
127.0.1.1
ist 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.
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)]
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'])
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:
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!
Hinweis: Dies ist nicht die Standardbibliothek, sondern recht einfach.
$ 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)
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.
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()
import socket
socket.gethostbyname(socket.getfqdn())
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).
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.
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.
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 .
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.
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.
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']
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).
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
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)
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]);"
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