Trovare gli indirizzi IP locali usando lo stdlib di Python
-
03-07-2019 - |
Domanda
Come posso trovare gli indirizzi IP locali (ovvero 192.168.x.x o 10.0.x.x) nella piattaforma Python in modo indipendente e usando solo la libreria standard?
Soluzione
import socket
socket.gethostbyname(socket.gethostname())
Non funzionerà sempre (restituisce 127.0.0.1
su macchine che hanno il nome host in / etc / hosts
come 127.0.0.1
) , un paliativo sarebbe ciò che gimel mostra, usare invece socket.getfqdn ()
. Ovviamente la tua macchina ha bisogno di un nome host risolvibile.
Altri suggerimenti
Ho appena trovato questo, ma sembra un po 'hacker, tuttavia dicono che l'ho provato su * nix e l'ho fatto su Windows e ha funzionato.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
Ciò presuppone che tu abbia un accesso a Internet e che non esiste un proxy locale.
Questo metodo restituisce il " primario " IP sulla casella locale (quella con un percorso predefinito) .
- NON necessita dell'accesso alla rete instradabile o di qualsiasi connessione.
- Funziona anche se tutte le interfacce sono scollegate dalla rete.
- NON ha bisogno o addirittura cerca di ottenere altrove .
- Funziona con NAT, pubblici, privati, esterni e IP interni
- Pure Python 2 (o 3) senza dipendenze esterne.
- Funziona su Linux, Windows e OSX.
Python 2 o 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
Questo restituisce un singolo IP che è il primario (quello con una route predefinita). Se invece hai bisogno di tutti gli IP collegati a tutte le interfacce (incluso localhost, ecc.), Vedi questa risposta .
Se sei dietro un firewall NAT come il tuo wifi box a casa, questo non mostrerà il tuo IP NAT pubblico, ma invece il tuo IP NAT privato sulla rete locale che ha un percorso predefinito al tuo router WIFI locale; ottenere l'IP esterno del tuo router wifi richiederebbe di eseguirlo su QUESTO box o di collegarti a un servizio esterno come whatismyip.com/whatismyipaddress.com che potrebbe riflettere l'IP ... ma è completamente diverso dalla domanda originale. :)
Chiamata connect () aggiornata secondo il suggerimento di Pedro nei commenti. (Se hai bisogno di una specifica dichiarazione di licenza, questo è di dominio pubblico / gratuito per qualsiasi uso, o MIT / CC2-BY-SA per codice / licenza di Stack Overflow a tua scelta.)
Come alias chiamato myip
, dovrebbe funzionare ovunque:
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])'"
- Funziona correttamente con Python 2.x, Python 3.x, distro Linux moderne e precedenti, OSX / macOS e Windows per trovare l'indirizzo IPv4 corrente.
- Non restituirà il risultato corretto per macchine con più indirizzi IP, IPv6, nessun indirizzo IP configurato o accesso a Internet.
Come sopra, ma solo il codice Python:
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])
- Ciò genererà un'eccezione se non è configurato alcun indirizzo IP.
Versione che funziona anche su LAN senza una connessione Internet:
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])
(grazie @ccpizza )
Sfondo :
L'uso di socket.gethostbyname (socket.gethostname ())
non ha funzionato qui, perché uno dei computer in cui mi trovavo aveva un / etc / hosts
con voci duplicate e riferimenti a se stesso. socket.gethostbyname ()
restituisce solo l'ultima voce in / etc / hosts
.
Questo è stato il mio tentativo iniziale, che ha eliminato tutti gli indirizzi che iniziano con " 127. "
:
import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
Funziona con Python 2 e 3, su Linux e Windows, ma non riguarda diversi dispositivi di rete o IPv6. Tuttavia, ha smesso di funzionare su recenti distribuzioni Linux, quindi ho provato questa tecnica alternativa. Tenta di connettersi al server DNS di Google in 8.8.8.8
nella porta 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])
Quindi ho combinato le due tecniche sopra descritte in un one-liner che dovrebbe funzionare ovunque e ho creato l'alias myip
e lo snippet Python in cima a questa risposta.
Con la crescente popolarità di IPv6 e per i server con più interfacce di rete, l'utilizzo di un modulo Python di terze parti per trovare l'indirizzo IP è probabilmente sia più robusto che affidabile rispetto a qualsiasi dei metodi elencati qui.
Puoi utilizzare il modulo netifaces . Basta digitare:
pip install netifaces
nella tua shell dei comandi e si installerà automaticamente sull'installazione predefinita di Python.
Quindi puoi usarlo in questo modo:
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))
Sul mio computer ha stampato:
{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207
L'autore di questo modulo afferma che dovrebbe funzionare su Windows, UNIX e Mac OS X.
Metodo API socket
vedi https://stackoverflow.com/a/28950776/711085
Svantaggi:
- Non multipiattaforma.
- Richiede più codice di fallback, legato all'esistenza di determinati indirizzi su Internet
- Anche questo non funzionerà se sei dietro un NAT
- Probabilmente crea una connessione UDP, non indipendente dalla disponibilità (solitamente dell'ISP) del DNS (vedi altre risposte per idee come l'utilizzo dell'8.8.8.8: il server (coincidente anche con il DNS) di Google)
- Assicurati di rendere INDIRIZZABILE l'indirizzo di destinazione, come un indirizzo IP numerico che è garantito per essere inutilizzato. NON utilizzare alcuni domini come fakesubdomain.google.com o somefakewebsite.com; continuerai a spammare quella parte (ora o in futuro) e anche a spammare le tue caselle di rete.
Metodo del riflettore
(Notare che ciò non risponde alla domanda dell'OP sull'indirizzo IP locale, ad esempio 192.168 ...; ti dà il tuo indirizzo IP pubblico, che potrebbe essere più desiderabile a seconda del caso d'uso.)
Puoi interrogare alcuni siti come whatismyip.com (ma con un'API), come:
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)
o se si utilizza python2:
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)
I vantaggi:
- Un aspetto positivo di questo metodo è la multipiattaforma
- Funziona da dietro brutte NAT (ad esempio il tuo router di casa).
Svantaggi (e soluzioni alternative):
- Richiede che questo sito Web sia attivo, che il formato non cambi (quasi sicuramente non lo farà) e che i server DNS funzionino. Si può mitigare questo problema interrogando anche altri riflettori di indirizzi IP di terze parti in caso di guasto.
- Possibile vettore di attacco se non si interrogano più riflettori (per impedire a un riflettore compromesso di dirti che il tuo indirizzo è qualcosa che non è) o se non usi HTTPS (per impedire un man-in-the- attacco medio fingendo di essere il server)
modifica : sebbene inizialmente pensassi che questi metodi fossero davvero sbagliati (a meno che tu non usi molti fallback, il codice potrebbe essere irrilevante tra molti anni), pone la domanda "cos'è Internet ? " ;. Un computer può avere molte interfacce che puntano a molte reti diverse. Per una descrizione più approfondita dell'argomento, google per gateway e percorsi
. Un computer può essere in grado di accedere a una rete interna tramite un gateway interno o di accedere alla rete mondiale tramite un gateway, ad esempio un router (in genere il caso). L'indirizzo IP locale richiesto dall'OP è ben definito rispetto a un singolo livello di collegamento, quindi è necessario specificare che (" è la scheda di rete o il cavo Ethernet, di cui stiamo parlando? & Quot ;). Potrebbero esserci più risposte non uniche a questa domanda, come proposto. Tuttavia, l'indirizzo IP globale sulla rete mondiale è probabilmente ben definito (in assenza di una massiccia frammentazione della rete): probabilmente il percorso di ritorno tramite il gateway che può accedere ai TLD.
Se il computer ha un percorso verso Internet, funzionerà sempre per ottenere l'indirizzo IP locale preferito, anche se / etc / hosts non è impostato correttamente.
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]
Su 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'
>>>
Sto usando il seguente modulo:
#!/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
Testato con Windows e Linux (e non richiede moduli aggiuntivi per quelli) destinato all'uso su sistemi che si trovano in una singola LAN basata su IPv4.
L'elenco fisso di nomi di interfaccia non funziona per le recenti versioni di Linux, che hanno adottato la modifica di systemd v197 per quanto riguarda i nomi di interfaccia prevedibili, come sottolineato da Alexander . In tali casi, è necessario sostituire manualmente l'elenco con i nomi delle interfacce sul proprio sistema o utilizzare un'altra soluzione come netifaces .
Lo uso sui miei computer Ubuntu:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
Questo non funziona.
Se non si desidera utilizzare pacchetti esterni e non si desidera fare affidamento su server Internet esterni, ciò potrebbe essere d'aiuto. È un esempio di codice che ho trovato su Ricerca codice Google e modificato per restituire le informazioni richieste:
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
Utilizzo:
>>> for addr in getIPAddresses():
>>> print addr
192.168.0.100
10.5.9.207
Poiché si basa su windll
, funzionerà solo su Windows.
Una versione che non credo sia stata ancora pubblicata. Ho provato con Python 2.7 su Ubuntu 12.04.
Trovato questa soluzione su: 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])
Esempio di risultato:
>>> get_ip_address('eth0')
'38.113.228.130'
Su Debian (testato) e sospetto che la maggior parte di Linux ...
import commands
RetMyIP = commands.getoutput("hostname -I")
Su MS Windows (testato)
import socket
socket.gethostbyname(socket.gethostname())
Variazione sulla risposta di ninjagecko. Questo dovrebbe funzionare su qualsiasi LAN che consenta la trasmissione UDP e non richieda l'accesso a un indirizzo su LAN o 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())
Temo che non ci siano buoni modi indipendenti dalla piattaforma per farlo oltre a collegarsi a un altro computer e farti inviare il tuo indirizzo IP. Ad esempio: findmyipaddress . Nota che questo non funzionerà se hai bisogno di un indirizzo IP dietro NAT a meno che anche il computer a cui ti stai connettendo sia dietro NAT.
Ecco una soluzione che funziona in Linux: ottieni l'indirizzo IP associato a un'interfaccia di rete .
Un modo semplice per produrre " clean " output tramite utils da riga di comando:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips
Mostrerà tutti gli indirizzi IPv4 sul sistema.
Cordiali saluti, posso verificare che il metodo:
import socket
addr = socket.gethostbyname(socket.gethostname())
Funziona su OS X (10.6,10.5), Windows XP e su un server dipartimentale RHEL ben amministrato. Non ha funzionato su una VM CentOS minimale su cui eseguo solo un po 'di hacking del kernel. Quindi, per quell'istanza, puoi semplicemente controllare un indirizzo 127.0.0.1 e in tal caso effettuare le seguenti operazioni:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
E quindi analizzare l'indirizzo IP dall'output. Va notato che per impostazione predefinita ifconfig non si trova nel PERCORSO di un normale utente ed è per questo che do il percorso completo nel comando. Spero che questo aiuti.
Questa è una variante della risposta di UnkwnTech: fornisce una funzione get_local_addr ()
, che restituisce l'indirizzo IP LAN primario dell'host. Lo sto pubblicando perché questo aggiunge una serie di cose: supporto ipv6, gestione degli errori, ignorando gli host localhost / linklocal e usa un indirizzo TESTNET (rfc5737) per connettersi.
# 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
Funzionerà sulla maggior parte dei box Linux:
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()
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
Questa risposta è il mio tentativo personale di risolvere il problema di ottenere l'IP LAN, poiché anche socket.gethostbyname (socket.gethostname ())
ha restituito 127.0.0.1. Questo metodo non richiede Internet solo una connessione LAN. Il codice è per Python 3.x ma potrebbe essere facilmente convertito per 2.x. Utilizzando UDP Broadcast:
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 __name__ == '__main__':
print(get_local_ip())
127.0.1.1
è il tuo vero indirizzo IP. Più in generale, un computer può avere un numero qualsiasi di indirizzi IP. Puoi filtrarli per reti private: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 e 192.168.0.0/16.
Tuttavia, non esiste un modo multipiattaforma per ottenere tutti gli indirizzi IP. Su Linux, puoi usare SIOCGIFCONF
ioctl.
Un leggero perfezionamento della versione dei comandi che utilizza il comando IP e restituisce gli indirizzi IPv4 e IPv6:
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)]
Bene, puoi usare il comando " ip route " su GNU / Linux per conoscere il tuo attuale indirizzo IP.
Questo mostra l'IP fornito all'interfaccia dal server DHCP in esecuzione sul router / modem. Di solito "192.168.1.1/24" è l'IP per la rete locale in cui "24" indica l'intervallo di indirizzi IP possibili forniti dal server DHCP all'interno dell'intervallo di maschere.
Ecco un esempio: nota che PyNotify è solo un'aggiunta per chiarire il mio punto di vista e non è richiesto affatto
#! /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()
Il vantaggio è che non è necessario specificare l'interfaccia di rete. È piuttosto utile quando si esegue un server socket
Puoi installare PyNotify usando easy_install o anche Pip:
easy_install py-notify
o
pip install py-notify
o all'interno di script / interprete python
from pip import main
main(['install', 'py-notify'])
Nota: questo non utilizza la libreria standard, ma piuttosto semplice.
$ pip install pif
from pif import get_public_ip
get_public_ip()
netifaces è disponibile tramite pip e easy_install. (Lo so, non è nella base, ma potrebbe valere la pena installarlo.)
netifaces ha delle stranezze tra le piattaforme:
- L'interfaccia localhost / loop-back potrebbe non essere sempre inclusa (Cygwin).
- Gli indirizzi sono elencati per protocollo (ad es. IPv4, IPv6) e i protocolli sono elencati per interfaccia. Su alcuni sistemi (Linux) ogni coppia protocollo-interfaccia ha la propria interfaccia associata (usando il nome interfaccia: notazione n) mentre su altri sistemi (Windows) una singola interfaccia avrà un elenco di indirizzi per ciascun protocollo. In entrambi i casi esiste un elenco di protocolli, ma può contenere solo un singolo elemento.
Ecco alcuni codici netifaces con cui giocare:
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.
Il codice sopra riportato non associa un indirizzo al suo nome di interfaccia (utile per generare al volo regole ebtables / iptables). Quindi ecco una versione che mantiene le informazioni sopra con il nome dell'interfaccia in una tupla:
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]
E, no, non sono innamorato della comprensione dell'elenco. In questi giorni funziona proprio come il mio cervello.
Il seguente frammento stamperà tutto:
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)
Enjoy!
Per ottenere l'indirizzo IP puoi usare un comando shell direttamente in python :
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 netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)
Questo ti restituirà l'indirizzo IP nel sistema Ubuntu e MacOS. L'output sarà l'indirizzo IP del sistema come il mio IP: 192.168.1.10.
Se stai cercando un indirizzo IPV4 diverso dal tuo indirizzo IP localhost 127.0.0.1
, ecco un bel pezzo di codici Python:
import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8')
address=address[:-1]
Che può anche essere scritto in una sola riga:
address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]
Anche se inserisci localhost
in / etc / hostname
, il codice fornirà comunque il tuo indirizzo IP locale.
Ho dovuto risolvere il problema "Capire se un indirizzo IP è locale o meno", e il mio primo pensiero è stato quello di costruire un elenco di IP locali e quindi confrontarli. Questo è ciò che mi ha portato a questa domanda. Tuttavia, in seguito ho capito che esiste un modo più diretto per farlo: prova a legare quell'IP e vedi se funziona.
_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
So che questo non risponde direttamente alla domanda, ma questo dovrebbe essere utile a chiunque cerchi di risolvere la domanda correlata e che seguisse lo stesso flusso di pensieri. Questo ha il vantaggio di essere una soluzione multipiattaforma (credo).