web-dev-qa-db-fra.com

Recherche d'adresses IP locales à l'aide de la bibliothèque stdlib de Python

Comment puis-je trouver des adresses IP locales (192.168.x.x ou 10.0.x.x) sur la plateforme Python indépendamment et en utilisant uniquement la bibliothèque standard?

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

Cela ne fonctionnera pas toujours (retourne 127.0.0.1 sur les machines dont le nom d’hôte est /etc/hosts sous la forme 127.0.0.1), un paliative serait ce que gimel affiche, utilisez plutôt socket.getfqdn(). Bien entendu, votre ordinateur a besoin d’un nom d’hôte pouvant être résolu.

374
Vinko Vrsalovic

Je viens de trouver cela, mais cela semble un peu ridicule, mais ils disent l'avoir essayé sur * nix et je l'ai fait sur les fenêtres et cela a fonctionné.

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

Cela suppose que vous avez un accès Internet et qu’il n’existe pas de proxy local.

389
UnkwnTech

Comme un alias appelé myip, cela devrait fonctionner partout:

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])'"
  • Fonctionne correctement avec Python 2.x, Python 3.x, les distributions Linux anciennes et modernes, OSX/macOS et Windows pour trouver l’adresse IPv4 actuelle.
  • Ne renverra pas le résultat correct pour les machines avec plusieurs adresses IP, IPv6, aucune adresse IP configurée ou aucun accès Internet.

Comme ci-dessus, mais uniquement le code 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])
  • Cela lève une exception si aucune adresse IP n'est configurée.

Version qui fonctionnera également sur les réseaux locaux sans connexion 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])

(merci @ccpizza )


Contexte:

L'utilisation de socket.gethostbyname(socket.gethostname()) ne fonctionnait pas ici, car l'un des ordinateurs sur lequel je me trouvais avait un /etc/hosts avec des entrées en double et des références à lui-même. socket.gethostbyname() ne renvoie que la dernière entrée dans /etc/hosts.

C’était ma tentative initiale, qui supprimait toutes les adresses commençant par "127.":

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

Cela fonctionne avec Python 2 et 3, sous Linux et Windows, mais ne traite pas avec plusieurs périphériques réseau ou IPv6. Cependant, il n’a plus fonctionné avec les distributions récentes de Linux, j’ai donc essayé cette technique alternative. Il essaie de se connecter au serveur DNS Google à l'adresse 8.8.8.8 au port 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])

Ensuite, j'ai combiné les deux techniques ci-dessus dans une ligne unique qui devrait fonctionner partout, et créé l'alias myip et l'extrait Python en haut de cette réponse.

Avec la popularité croissante d'IPv6 et pour les serveurs dotés de plusieurs interfaces réseau, l'utilisation d'un module Python tiers pour rechercher l'adresse IP est probablement à la fois plus robuste et fiable que toutes les méthodes répertoriées ici.

135
Alexander

Cette méthode renvoie l'adresse IP "principale" de la boîte locale (celle avec une route par défaut).

  • N'a PAS besoin d'un accès réseau routable ou d'une connexion du tout.
  • Fonctionne même si toutes les interfaces sont débranchées du réseau.
  • N'a PAS besoin ou même n'essaye pas d'obtenir nulle part ailleurs.
  • Fonctionne avec les adresses IP NAT, publiques, privées, externes et internes
  • Pure Python 2 (ou 3) sans dépendance externe.
  • Fonctionne sous Linux, Windows et OSX.

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

Cela renvoie une seule adresse IP qui est la principale (celle avec une route par défaut). Si vous avez besoin de toutes les adresses IP attachées à toutes les interfaces (y compris localhost, etc.), voir cette réponse .

Si vous êtes derrière un pare-feu NAT tel que votre wifi box chez vous, cela ne montrera pas votre IP publique NAT, mais votre IP privée NAT sur le réseau local qui a une valeur par défaut. route vers votre routeur WIFI local; Obtenir l'IP externe de votre routeur wifi nécessiterait soit de l'exécuter sur That Box, soit de se connecter à un service externe tel que whatismyip.com/whatismyipaddress.com qui pourrait refléter l'IP ... mais cela est complètement différent de la question initiale. :)

Appel mis à jour (connect) par suggestion de Pedro dans les commentaires. (Si vous avez besoin d'une déclaration de licence spécifique, il s'agit d'un domaine public/gratuit pour toute utilisation, ou d'une licence de code/contenu MIT/CC2-BY-SA par pile, selon votre choix.)

134
Jamieson Becker

Vous pouvez utiliser le module netifaces . Il suffit de taper:

pip install netifaces

dans votre commande Shell et il s’installera lui-même sur l’installation par défaut de Python.

Ensuite, vous pouvez l'utiliser comme ceci:

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

Sur mon ordinateur, il imprimait:

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

L'auteur de ce module affirme qu'il devrait fonctionner sous Windows, UNIX et Mac OS X.

82
DzinX

Méthode de l'API Socket

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

Inconvénients:

  • Pas multiplateforme.
  • Nécessite davantage de code de secours, lié à l'existence d'adresses particulières sur Internet
  • Cela ne fonctionnera pas non plus si vous êtes derrière un NAT
  • Crée probablement une connexion UDP, non indépendante de la disponibilité DNS (généralement du FAI) (voir d'autres réponses pour des idées comme utiliser 8.8.8.8: le serveur de Google (par coïncidence, aussi le serveur DNS))
  • Assurez-vous que l'adresse de destination est inaccessible, par exemple une adresse IP numérique dont la garantie spécifiée est inutilisée. N'utilisez PAS un domaine tel que fakesubdomain.google.com ou somefakewebsite.com; vous continuerez à envoyer des spams à cette partie (maintenant ou à l'avenir) et à envoyer vos propres boîtes réseau par la même occasion.

Méthode du réflecteur

(Notez que cela ne répond pas à la question de l'adresse IP locale posée par l'OP, par exemple 192.168 ...; il vous donne votre adresse IP publique, qui pourrait être plus souhaitable, selon le cas d'utilisation.)

Vous pouvez interroger certains sites tels que whatismyip.com (mais avec une API), tels que:

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)

ou si vous utilisez 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)

Avantages:

  • Un des avantages de cette méthode est sa multiplateforme
  • Il fonctionne derrière des NATs laids (par exemple votre routeur domestique).

Inconvénients (et solutions de contournement):

  • Nécessite que ce site Web soit opérationnel, que le format ne soit pas modifié (presque certainement pas) et que vos serveurs DNS fonctionnent. On peut résoudre ce problème en interrogeant également d'autres réflecteurs d'adresse IP tiers en cas de défaillance.
  • Vecteur d’attaque possible si vous n’interrogez pas plusieurs réflecteurs (pour empêcher un réflecteur compromis de vous dire que votre adresse est quelque chose qui ne l’est pas), ou si vous n’utilisez pas HTTPS (pour empêcher une attaque factice de type homme au milieu) être le serveur)

edit: Bien qu'initialement je pensais que ces méthodes étaient vraiment mauvaises (à moins que vous n'utilisiez beaucoup de solutions de repli, le code risque de ne plus être pertinent dans plusieurs années), il pose la question "qu'est-ce qu'Internet?". Un ordinateur peut avoir de nombreuses interfaces pointant vers plusieurs réseaux différents. Pour une description plus détaillée du sujet, consultez Google pour gateways and routes. Un ordinateur peut être en mesure d'accéder à un réseau interne via une passerelle interne ou au Web via une passerelle, par exemple un routeur (généralement le cas). L’adresse IP locale sur laquelle l’opérateur pose des questions n’est définie que de manière précise par rapport à une seule couche de liaison; vous devez donc spécifier cela ("s’agit-il de la carte réseau ou du câble Ethernet dont nous parlons?") . Il peut y avoir plusieurs réponses non uniques à cette question telle que posée. Toutefois, l’adresse IP globale sur le Web est probablement bien définie (en l’absence de fragmentation massive du réseau): probablement le chemin de retour via la passerelle permettant d’accéder aux TLD.

48
ninjagecko

Si l'ordinateur est connecté à Internet, toujours fonctionnera pour obtenir l'adresse IP locale préférée, même si/etc/hosts n'est pas défini correctement.

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(('8.8.8.8', 1))  # connect() for UDP doesn't send packets
local_ip_address = s.getsockname()[0]
40
Collin Anderson

Sous Linux:

>>> import socket, struct, fcntl
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sockfd = sock.fileno()
>>> SIOCGIFADDR = 0x8915
>>>
>>> def get_ip(iface = 'eth0'):
...     ifreq = struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
...     try:
...         res = fcntl.ioctl(sockfd, SIOCGIFADDR, ifreq)
...     except:
...         return None
...     ip = struct.unpack('16sH2x4s8x', res)[2]
...     return socket.inet_ntoa(ip)
... 
>>> get_ip('eth0')
'10.80.40.234'
>>> 
38
tMC

im utilisant le module suivant:

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

Testé avec Windows et Linux (et ne nécessite pas de modules supplémentaires pour ceux-ci) Destiné à être utilisé sur des systèmes utilisant un seul réseau local basé sur IPv4.

La liste fixe des noms d'interface ne fonctionne pas pour les versions récentes de Linux, qui ont adopté la modification de systemd v197 concernant les noms d'interface prévisibles, comme indiqué par Alexander . Dans ce cas, vous devez remplacer manuellement la liste par les noms d’interface de votre système ou utilisez une autre solution telle que netifaces .

26
smerlin

J'utilise ceci sur mes machines Ubuntu:

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

Ça ne marche pas.

24
shino

Si vous ne souhaitez pas utiliser de packages externes et ne souhaitez pas vous fier à des serveurs Internet extérieurs, cela pourrait vous aider. C'est un exemple de code que j'ai trouvé sur Google Code Search et modifié pour renvoyer les informations requises:

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

Usage:

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

Comme il repose sur windll, cela ne fonctionnera que sous Windows.

19
DzinX

Je ne crois pas que cette version ait été publiée pour le moment. J'ai testé avec Python 2.7 sur Ubuntu 12.04.

Vous avez trouvé cette solution à: 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])

Exemple de résultat:

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

Sur Debian (testé) et je soupçonne la plupart des systèmes Linux ..

import commands

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

Sur MS Windows (testé) 

import socket

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

Variation sur la réponse de ninjagecko. Cela devrait fonctionner sur tout réseau local permettant la diffusion UDP et ne nécessitant pas d'accès à une adresse du réseau local ou d'Internet.

import socket
def getNetworkIp():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    s.connect(('<broadcast>', 0))
    return s.getsockname()[0]

print (getNetworkIp())
9
dlm

Un moyen simple de produire une sortie "propre" via des utilitaires en ligne de commande:

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

Il montrera toutes les adresses IPv4 sur le système.

8
viker

J'ai bien peur qu'il n'y ait pas de bonne façon de procéder, indépendamment de la plate-forme, autre que la connexion à un autre ordinateur et que celui-ci vous envoie votre adresse IP. Par exemple: findmyipaddress . Notez que cela ne fonctionnera pas si vous avez besoin d'une adresse IP située derrière NAT, sauf si l'ordinateur auquel vous vous connectez se trouve également derrière NAT.

Voici une solution qui fonctionne sous Linux: obtenir l’adresse IP associée à une interface réseau .

8
Jason Baker

Ceci est une variante de la réponse de UnkwnTech - elle fournit une fonction get_local_addr(), qui renvoie l'adresse IP de réseau local principale de l'hôte. Je le publie car cela ajoute un certain nombre d'éléments: prise en charge d'ipv6, traitement des erreurs, ignorant les adresses localhost/linklocal et utilise un compte TESTNET (rfc5737) pour se connecter.

# imports
import errno
import socket

# localhost prefixes
_local_networks = ("127.", "0:0:0:0:0:0:0:1")

# ignore these prefixes -- localhost, unspecified, and link-local
_ignored_networks = _local_networks + ("0.", "0:0:0:0:0:0:0:0", "169.254.", "fe80:")

def detect_family(addr):
    if "." in addr:
        assert ":" not in addr
        return socket.AF_INET
    Elif ":" in addr:
        return socket.AF_INET6
    else:
        raise ValueError("invalid ipv4/6 address: %r" % addr)

def expand_addr(addr):
    """convert address into canonical expanded form --
    no leading zeroes in groups, and for ipv6: lowercase hex, no collapsed groups.
    """
    family = detect_family(addr)
    addr = socket.inet_ntop(family, socket.inet_pton(family, addr))
    if "::" in addr:
        count = 8-addr.count(":")
        addr = addr.replace("::", (":0" * count) + ":")
        if addr.startswith(":"):
            addr = "0" + addr
    return addr

def _get_local_addr(family, remote):
    try:
        s = socket.socket(family, socket.SOCK_DGRAM)
        try:
            s.connect((remote, 9))
            return s.getsockname()[0]
        finally:
            s.close()
    except socket.error:
        return None

def get_local_addr(remote=None, ipv6=True):
    """get LAN address of Host

    :param remote:
        return  LAN address that Host would use to access that specific remote address.
        by default, returns address it would use to access the public internet.

    :param ipv6:
        by default, attempts to find an ipv6 address first.
        if set to False, only checks ipv4.

    :returns:
        primary LAN address for Host, or ``None`` if couldn't be determined.
    """
    if remote:
        family = detect_family(remote)
        local = _get_local_addr(family, remote)
        if not local:
            return None
        if family == socket.AF_INET6:
            # expand zero groups so the startswith() test works.
            local = expand_addr(local)
        if local.startswith(_local_networks):
            # border case where remote addr belongs to Host
            return local
    else:
        # NOTE: the two addresses used here are TESTNET addresses,
        #       which should never exist in the real world.
        if ipv6:
            local = _get_local_addr(socket.AF_INET6, "2001:db8::1234")
            # expand zero groups so the startswith() test works.
            if local:
                local = expand_addr(local)
        else:
            local = None
        if not local:
            local = _get_local_addr(socket.AF_INET, "192.0.2.123")
            if not local:
                return None
    if local.startswith(_ignored_networks):
        return None
    return local
7
Eli Collins

Pour info je peux vérifier que la méthode:

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

Fonctionne sous OS X (10.6,10.5), Windows XP et sur un serveur de département RHEL bien administré. Cela n’a pas fonctionné avec un minimum de CentOS VM sur lequel je viens de faire du piratage du noyau. Donc, pour cette instance, vous pouvez simplement rechercher une adresse 127.0.0.1 et dans ce cas, procédez comme suit:

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

Et puis analyser l'adresse ip de la sortie. Il est à noter que ifconfig n'est pas dans le PATH d'un utilisateur normal par défaut et c'est pourquoi je donne le chemin complet dans la commande. J'espère que ça aide.

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

Cela fonctionnera sur la plupart des boîtes 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()
6
fccoelho

Cette réponse est ma tentative personnelle de résoudre le problème d'obtention de l'adresse IP du réseau local, puisque socket.gethostbyname(socket.gethostname()) a également renvoyé 127.0.0.1. Cette méthode ne nécessite pas d’Internet mais seulement une connexion LAN. Le code est pour Python 3.x mais pourrait facilement être converti pour 2.x. Utilisation de la diffusion UDP:

import select
import socket
import threading
from queue import Queue, Empty

def get_local_ip():
        def udp_listening_server():
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.bind(('<broadcast>', 8888))
            s.setblocking(0)
            while True:
                result = select.select([s],[],[])
                msg, address = result[0][0].recvfrom(1024)
                msg = str(msg, 'UTF-8')
                if msg == 'What is my LAN IP address?':
                    break
            queue.put(address)

        queue = Queue()
        thread = threading.Thread(target=udp_listening_server)
        thread.queue = queue
        thread.start()
        s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        waiting = True
        while waiting:
            s2.sendto(bytes('What is my LAN IP address?', 'UTF-8'), ('<broadcast>', 8888))
            try:
                address = queue.get(False)
            except Empty:
                pass
            else:
                waiting = False
        return address[0]

if __== '__main__':
    print(get_local_ip())
5
WolfRage

127.0.1.1est votre adresse IP réelle. Plus généralement, un ordinateur peut avoir un nombre quelconque d'adresses IP. Vous pouvez les filtrer pour les réseaux privés - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 et 192.168.0.0/16.

Cependant, il n'y a pas de moyen multiplateforme d'obtenir toutes les adresses IP. Sous Linux, vous pouvez utiliser l'ioctl SIOCGIFCONF _.

4
phihag

Un léger raffinement de la version des commandes qui utilise la commande IP et renvoie les adresses IPv4 et 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)]
4
Ben Last

Eh bien, vous pouvez utiliser la commande "ip route" sur GNU/Linux pour connaître votre adresse IP actuelle.

Ceci montre l’adresse IP donnée à l’interface par le serveur DHCP fonctionnant sur le routeur/modem. Habituellement, "192.168.1.1/24" est l'adresse IP du réseau local, où "24" correspond à la plage d'adresses IP possibles indiquée par le serveur DHCP dans la plage de masque.

Voici un exemple: Notez que PyNotify est juste un ajout pour que mon point soit clair et n’est pas requis du tout.

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

L'avantage de cela est qu'il n'est pas nécessaire de spécifier l'interface réseau. C'est très utile lors de l'exécution d'un serveur de socket

Vous pouvez installer PyNotify en utilisant easy_install ou même Pip:

easy_install py-notify

ou

pip install py-notify

ou dans un script/interprète python

from pip import main

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

netifaces est disponible via pip et easy_install. (Je sais, ce n'est pas en base, mais cela pourrait valoir la peine d'être installé.)

netifaces a quelques bizarreries sur toutes les plateformes:

  • L'interface localhost/loop-back peut ne pas toujours être incluse (Cygwin).
  • Les adresses sont répertoriées par protocole (par exemple, IPv4, IPv6) et les protocoles par interface. Sur certains systèmes (Linux), chaque paire d’interface protocole a sa propre interface associée (utilisant la notation nom_interface: n) alors que sur d’autres systèmes (Windows), une seule interface possède une liste d’adresses pour chaque protocole. Dans les deux cas, il existe une liste de protocoles, mais celle-ci peut ne contenir qu'un seul élément.

Voici quelques codes de netifaces pour jouer avec:

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.

Le code ci-dessus ne mappe pas une adresse sur son nom d'interface (utile pour générer des règles ebtables/iptables à la volée). Voici donc une version qui conserve les informations ci-dessus avec le nom de l'interface dans un tuple:

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]

Et non, je ne suis pas amoureuse des compréhensions de liste. C'est juste la façon dont mon cerveau fonctionne ces jours-ci.

L'extrait suivant va tout imprimer:

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)

Prendre plaisir!

3
user3712955

Note: Ceci n'utilise pas la bibliothèque standard, mais assez simple.

$ pip install pif

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

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

Cela vous retournera l'adresse IP dans le système Ubuntu ainsi que MacOS. La sortie sera l'adresse IP du système comme mon adresse IP: 192.168.1.10.

3
Ishwarya

Pour obtenir l'adresse IP, vous pouvez utiliser une commande Shell directement dans 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()
3
RiccardoCh
import socket
socket.gethostbyname(socket.getfqdn())
2
Oink

Je devais résoudre le problème "Déterminer si une adresse IP est locale ou non", et ma première idée fut de créer une liste d'adresses IP locales, puis de les comparer. C'est ce qui m'a amené à cette question. Cependant, j'ai réalisé par la suite qu'il existait un moyen plus simple de le faire: essayez de vous lier sur cette adresse IP et de voir si cela fonctionne.

_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

Je sais que cela ne répond pas directement à la question, mais cela devrait être utile à quiconque tente de résoudre la question connexe et qui suit le même train de pensées. Cela a l'avantage d'être une solution multi-plateforme (je pense).

2
Etienne Perot

Pour obtenir une liste des adresses IP sur les systèmes * nix,

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

Bien qu'il soit un peu tard pour cette réponse, j'ai pensé que quelqu'un d'autre pourrait la trouver utile :-)

PS: Il retournera également les adresses de diffusion et le masque de réseau.

1
Kulbir Saini

Ce n'est pas très Pythonic, mais cela fonctionne de manière fiable sur 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()

Oui, c'est un bidouillage, mais parfois, je n'ai pas le goût de deviner un système d'exploitation, et d'aller de l'avant et d'utiliser ce qui est intégré et qui fonctionne.

1
LRund

Une version Python 3.4 utilisant le package asyncio nouvellement introduit.

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

Ceci est basé sur UnkwnTech excellente réponse .

1
Frederik Aalund

Si vous recherchez une adresse IPV4 différente de votre adresse IP localhost 127.0.0.1, voici un bon morceau de codes python:

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

Ce qui peut aussi être écrit en une seule ligne:

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

Même si vous mettez localhost dans /etc/hostname, le code donnera toujours votre adresse IP locale.

1
hmofrad

Ok, ceci est donc spécifique à Windows et nécessite l’installation du module python WMI , mais cela semble beaucoup moins compliqué que de constamment essayer d’appeler un serveur externe. C'est juste une autre option, car il y a déjà beaucoup de bonnes, mais cela pourrait être un bon choix pour votre projet.

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

Soit dit en passant, WMI est très puissant ... si vous faites l’administration distante de machines Windows, vous devez absolument vérifier ce qu’elle peut faire.

1
snakebarber
from netifaces import interfaces, ifaddresses, AF_INET
iplist = [ifaddresses(face)[AF_INET][0]["addr"] for face in interfaces() if AF_INET in ifaddresses(face)]
print(iplist)
['10.8.0.2', '192.168.1.10', '127.0.0.1']
0
Villiam

Une machine peut avoir plusieurs interfaces réseau (y compris la boucle locale 127.0.0.1) que vous avez mentionnée. En ce qui concerne le système d'exploitation, il s'agit également d'une "adresse IP réelle". 

Si vous souhaitez suivre toutes les interfaces, consultez le paquet Puthon suivant: http://alastairs-place.net/netifaces/

Je pense que vous pouvez éviter que gethostbyname renvoie 127.0.0.1 si vous omettez l'entrée en boucle à partir de votre fichier hosts. (à vérifier).

0
ddewaele

Encore une autre variante des réponses précédentes peut être sauvegardée dans un script exécutable nommé my-ip-to:

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

il faut un nombre quelconque d’hôtes distants et imprimer des ips locaux pour les atteindre un par un:

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

Et imprimez le meilleur pari quand aucun argument n'est donné.

$ my-ip-to
192.168.11.102
0
Compl Yue

Pour Linux, vous pouvez simplement utiliser check_output de la commande système hostname -I comme ceci:

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

Simple mais doux!

def getip():

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

    return(ip)
0
Matt

Ceci est très similaire aux réponses précédemment postées, mais je n’en ai trouvé aucune avec cet usage des appels. C'est ce que j'utilise pour ipv4. Pour ipv6, changez le '.' dans ':' dans 

import socket
print next(i[4][0] for i in socket.getaddrinfo(
    socket.gethostname(), 80) if '127.' not in i[4][0] and '.' in i[4][0]);"
0
Wyrmwood

Pour un env Linux, lisez le fichier/proc/net/tcp, le second (adresse locale) et le troisième (remoteaddress) donneront les adresses IP au format hexa.

Conseil: Si la deuxième colonne est mise à zéro (00000000: 0000), c’est un port d'écoute :)

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

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

0
Romolo