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?

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top