Question

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?

Était-ce utile?

La solution

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

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

Autres conseils

Je viens de trouver cela, mais cela semble un peu féroce, mais ils disent l'avoir essayé sur * nix et moi, sur Windows 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.

Cette méthode retourne le " primaire " IP sur la boîte locale (celle avec une route par défaut) .

  • N'a PAS besoin d'un accès réseau routable ni d'aucune connexion.
  • Fonctionne même si toutes les interfaces sont débranchées du réseau.
  • N'a PAS besoin ni même essayé 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

Ceci renvoie une seule adresse IP qui est la principale (celle avec une route par défaut). Si vous avez plutôt 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 adresse IP publique, mais votre adresse IP privée sur le réseau local qui a une route par défaut 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.)

En tant qu'alias appelé myip , il 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 renvoie pas le résultat correct pour les ordinateurs dotés de plusieurs adresses IP, IPv6, sans adresse IP configurée ou sans 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])
  • Ceci 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 )

Arrière-plan :

L'utilisation de socket.gethostbyname (socket.gethostname ()) ne fonctionnait pas ici, car l'un des ordinateurs sur lequel j'avais l'ordinateur possédait 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 de / 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])

Ceci 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 tente de se connecter au serveur DNS Google à 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.

Compte tenu de la popularité croissante d’IPv6 et des 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 l’une des méthodes répertoriées ici.

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

pip install netifaces

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

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 a imprimé:

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

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 celle du fournisseur de services Internet (voir d'autres réponses, par exemple), comme l'utilisation de 8.8.8.8: le serveur de Google (par coïncidence, DNS également)
  • 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 en fonction du 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:

  • L'un des avantages de cette méthode est qu'il est multi-plateforme
  • Cela fonctionne derrière des NATs laids (par exemple, votre routeur domestique).

Inconvénients (et solutions de contournement):

  • Exige que ce site Web soit disponible, que le format ne soit pas modifié (ne changera certainement pas) et que vos serveurs DNS fonctionnent. On peut remédier à ce problème en interrogeant également d'autres réflecteurs d'adresses 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 qu’elle n’est pas), ou si vous n’utilisez pas HTTPS (pour empêcher toute intrusion attaque médiatique prétendant être le serveur)

modifier : bien qu'initialement, je trouvais ces méthodes très mauvaises (à moins d'utiliser beaucoup de solutions de repli, le code risque de ne plus être pertinent dans plusieurs années), mais le problème est de savoir quel est Internet. ? ". Un ordinateur peut avoir plusieurs interfaces pointant vers plusieurs réseaux différents. Pour une description plus détaillée du sujet, consultez Google pour les passerelles et itinéraires . Un ordinateur peut être en mesure d'accéder à un réseau interne via une passerelle interne ou d'accéder 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 couche de liaison unique; vous devez donc spécifier cette adresse (" il s’agit de la carte réseau ou du câble Ethernet, dont il est question?) ;). Il peut y avoir plusieurs réponses non uniques à cette question telle que posée. Cependant, l’adresse IP globale sur le World Wide 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.

Si l'ordinateur est connecté à Internet, toujours cela 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]

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

j'utilise 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 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 utiliser une autre solution, telle que . netifaces .

J'utilise ceci sur mes machines Ubuntu:

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

Cela ne fonctionne pas.

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é dans la recherche dans le code Google 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

Utilisation:

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

Une version qui, à mon avis, n’a pas encore été publiée. J'ai testé avec Python 2.7 sur Ubuntu 12.04.

Cette solution a été trouvée à: 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'

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

import commands

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

Sous MS Windows (testé)

import socket

socket.gethostbyname(socket.gethostname())

Variation sur la réponse de ninjagecko. Cela devrait fonctionner sur tout réseau local permettant la diffusion UDP et ne nécessitant pas l'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())

J’ai bien peur qu’il n’existe pas de bonne façon de procéder, indépendamment de la plate-forme, que de vous connecter à un autre ordinateur et de vous le faire envoyer par votre adresse IP. Par exemple, findmyipaddress . Notez que cela ne fonctionnera pas si vous avez besoin d'une adresse IP derrière NAT, à moins que l'ordinateur auquel vous vous connectez le soit également.

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

Un moyen simple de produire "propre" sortie via les utilitaires de 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

Toutes les adresses IPv4 du système seront affichées.

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 ne fonctionnait pas sur une machine virtuelle CentOS très minimale sur laquelle 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)

Ensuite, analysez 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 cela aide.

Ceci est une variante de la réponse de UnkwnTech. Il fournit une fonction get_local_addr () , qui renvoie l'adresse IP de réseau local principale de l'hôte. Je le publie parce que 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

Ceci 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()
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]

Cette réponse est ma tentative personnelle de résolution du problème d'obtention de l'adresse IP du réseau local, car 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 __name__ == '__main__':
    print(get_local_ip())

127.0.1.1 est 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'existe pas de moyen multiplateforme pour obtenir toutes les adresses IP. Sous Linux, vous pouvez utiliser l'ioctl SIOCGIFCONF .

Légère amélioration de la version de la commande 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)]

Vous pouvez utiliser la commande " ip route " sous GNU / Linux pour connaître votre adresse IP actuelle.

Ceci affiche l'adresse IP donnée à l'interface par le serveur DHCP s'exécutant sur le routeur / modem. Généralement " 192.168.1.1/24" est l’IP du réseau local où " 24 " désigne 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 obligatoire 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 à l’aide de easy_install ou même du Pip:

easy_install py-notify

ou

pip install py-notify

ou dans un script / interpréteur python

from pip import main

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

Remarque: ceci n'utilise pas la bibliothèque standard, mais plutôt simple.

$ pip install pif

from pif import get_public_ip
get_public_ip()

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

netifaces a quelques particularités 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 interface de protocole a sa propre interface associée (utilisant la notation nom_interface: n), tandis que sur d'autres systèmes (Windows), une interface unique possède une liste d'adresses pour chaque protocole. Dans les deux cas, il existe une liste de protocoles, mais elle ne peut contenir qu'un seul élément.

Voici quelques codes de netifaces avec lesquels jouer:

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 la façon dont mon cerveau fonctionne de nos jours.

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)

Profitez!

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()
import netifaces as ni 

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

Ceci vous retournera l'adresse IP dans le système Ubuntu ainsi que dans MacOS. La sortie sera l’adresse IP du système, telle que mon adresse IP: 192.168.1.10.

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 également être écrit sur une seule ligne:

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

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

Je devais résoudre le problème "Déterminer si une adresse IP est locale ou non", et ma première idée était 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 procéder: essayez de vous lier à cette adresse IP et de voir si elle 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 multiplate-forme (je pense).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top