web-dev-qa-db-fra.com

Comment puis-je obtenir l'adresse IP de eth0 en Python?

Lorsqu'une erreur survient dans un script Python sous Unix, un courrier électronique est envoyé.

On m'a demandé d'ajouter {Testing Environment} à la ligne d'objet de l'e-mail si l'adresse IP est 192.168.100.37, qui est le serveur de test. De cette façon, nous pouvons avoir une version d'un script et un moyen de savoir si l'e-mail provient de données altérées sur le serveur de test.

Cependant, quand je recherche sur Google, je continue à trouver ce code

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

Cependant, cela me donne l'adresse IP 127.0.1.1. Quand j'utilise ifconfig je reçois ce

eth0      Link encap:Ethernet  HWaddr 00:1c:c4:2c:c8:3e
          inet addr:192.168.100.37  Bcast:192.168.100.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:75760697 errors:0 dropped:411180 overruns:0 frame:0
          TX packets:23166399 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:59525958247 (59.5 GB)  TX bytes:10142130096 (10.1 GB)
          Interrupt:19 Memory:f0500000-f0520000

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:25573544 errors:0 dropped:0 overruns:0 frame:0
          TX packets:25573544 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:44531490070 (44.5 GB)  TX bytes:44531490070 (44.5 GB)

Tout d'abord, je ne sais pas d'où il vient 127.0.1.1, mais de toute façon ce n'est pas ce que je veux. Quand je recherche sur Google, je continue à utiliser la même syntaxe, Bash scripts ou netifaces et j'essaie d'utiliser des bibliothèques standard.

Alors, comment puis-je obtenir l'adresse IP de eth0 en Python?

54
Memor-X

Deux méthodes:

Méthode n ° 1 (utiliser un package externe)

Vous devez demander l'adresse IP liée à votre interface eth0. Ceci est disponible à partir du paquet netifaces

import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print ip  # should print "192.168.100.37"

Vous pouvez également obtenir une liste de toutes les interfaces disponibles via

ni.interfaces()

Méthode n ° 2 (pas de paquet externe)

Voici un moyen d'obtenir l'adresse IP sans utiliser de package python:

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

get_ip_address('eth0')  # '192.168.0.110'

Remarque: détecter l’adresse IP pour déterminer l’environnement que vous utilisez est un sacré bidouillage. Presque tous les frameworks fournissent un moyen très simple de définir/modifier une variable d'environnement pour indiquer l'environnement actuel. Essayez de consulter votre documentation à ce sujet. Cela devrait être aussi simple que de faire

if app.config['ENV'] == 'production':
  #send production email
else:
  #send development email
143
Martin Konecny

Sinon, si vous voulez obtenir l'adresse IP de l'interface utilisée pour vous connecter au réseau sans connaître son nom, vous pouvez utiliser ceci:

import socket
def get_ip_address():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))
    return s.getsockname()[0]

Je sais que c'est un peu différent de votre question, mais d'autres peuvent arriver ici et trouver celle-ci plus utile. Vous n'avez pas besoin d'avoir un itinéraire vers 8.8.8.8 pour l'utiliser. Tout ce qu'il fait est d'ouvrir un socket, mais n'envoie aucune donnée.

88
jeremyjjbrown

Une approche simple qui renvoie une chaîne d'adresses IP pour les interfaces est la suivante:

from subprocess import check_output

ips = check_output(['hostname', '--all-ip-addresses'])

pour plus d'informations, voir hostname .

24
Alexander

Si vous ne devez travailler que sous Unix, vous pouvez utiliser un appel système (réf. Question Stack Overflow Analyser ifconfig pour obtenir uniquement mon adresse IP à l'aide de Bash):

import os
f = os.popen('ifconfig eth0 | grep "inet\ addr" | cut -d: -f2 | cut -d" " -f1')
your_ip=f.read()
15
olmerg

Puisque la plupart des réponses utilisent ifconfig pour extraire l'IPv4 de l'interface eth0, qui est déconseillée pour ip addr, le code suivant pourrait être utilisé à la place:

import os

ipv4 = os.popen('ip addr show eth0 | grep "\<inet\>" | awk \'{ print $2 }\' | awk -F "/" \'{ print $1 }\'').read().strip()
ipv6 = os.popen('ip addr show eth0 | grep "\<inet6\>" | awk \'{ print $2 }\' | awk -F "/" \'{ print $1 }\'').read().strip()

METTRE À JOUR:

Sinon, vous pouvez déplacer une partie de la tâche d'analyse vers l'interpréteur python en utilisant split() au lieu de grep et awk, comme le souligne @serg dans le commentaire:

import os

ipv4 = os.popen('ip addr show eth0').read().split("inet ")[1].split("/")[0]
ipv6 = os.popen('ip addr show eth0').read().split("inet6 ")[1].split("/")[0]

Mais dans ce cas, vous devez vérifier les limites du tableau renvoyé par chaque appel split().

MISE À JOUR 2:

Une autre version utilisant regex:

import os
import re

ipv4 = re.search(re.compile(r'(?<=inet )(.*)(?=\/)', re.M), os.popen('ip addr show eth0').read()).groups()[0]
ipv6 = re.search(re.compile(r'(?<=inet6 )(.*)(?=\/)', re.M), os.popen('ip addr show eth0').read()).groups()[0]
14
Ivan De Paz Centeno

essayez ci-dessous le code, cela fonctionne pour moi dans Mac10.10.2:

import subprocess

if __== "__main__":
    result = subprocess.check_output('ifconfig en0 |grep -w inet', Shell=True) # you may need to use eth0 instead of en0 here!!!
    print 'output = %s' % result.strip()
    # result = None
    ip = ''
    if result:
        strs = result.split('\n')
        for line in strs:
            # remove \t, space...
            line = line.strip()
            if line.startswith('inet '):
                a = line.find(' ')
                ipStart = a+1
                ipEnd = line.find(' ', ipStart)
                if a != -1 and ipEnd != -1:
                    ip = line[ipStart:ipEnd]
                    break
    print 'ip = %s' % ip
2
xiaoweiz

S'appuyant sur la réponse de @jeremyjjbrown, une autre version qui nettoie après elle-même comme mentionné dans les commentaires de sa réponse Cette version permet également de fournir une adresse de serveur différente pour une utilisation sur des réseaux internes privés, etc.

import socket

def get_my_ip_address(remote_server="google.com"):
    """
    Return the/a network-facing IP number for this system.
    """
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: 
        s.connect((remote_server, 80))
        return s.getsockname()[0]
1
Steve Cohen

Recherchez l'adresse IP de la première entrée eth/wlan dans ifconfig qui est en cours d'exécution:

import itertools
import os
import re

def get_ip():
    f = os.popen('ifconfig')
    for iface in [' '.join(i) for i in iter(lambda: list(itertools.takewhile(lambda l: not l.isspace(),f)), [])]:
        if re.findall('^(eth|wlan)[0-9]',iface) and re.findall('RUNNING',iface):
            ip = re.findall('(?<=inet\saddr:)[0-9\.]+',iface)
            if ip:
                return ip[0]
    return False
0
Giles Greenway

Ça a fonctionné pour moi 

 import subprocess
 my_ip = subprocess.Popen(['ifconfig eth0 | awk "/inet /" | cut -d":" -f 2 | cut -d" " -f1'], stdout=subprocess.PIPE, Shell=True)
 (IP,errors) = my_ip.communicate()
 my_ip.stdout.close()
 print IP
0
Abhijit

Encore une autre façon d’obtenir l’adresse IP d’une carte réseau en utilisant Python.

J'avais cela dans le cadre d'une application que j'avais développée il y a longtemps, et je ne voulais pas simplement faire git rm script.py. Donc, je présente ici l'approche, en utilisant subprocess et liste les compréhensions dans un souci d'approche fonctionnelle et moins de lignes de code:

import subprocess as sp

__version__ = "v1.0"                                                            
__author__ = "@ivanleoncz"

def get_nic_ipv4(nic):                                                          
    """
        Get IP address from a NIC.                                              

        Parameter
        ---------
        nic : str
            Network Interface Card used for the query.                          

        Returns                                                                 
        -------                                                                 
        ipaddr : str
            Ipaddress from the NIC provided as parameter.                       
    """                                                                         
    result = None                                                               
    try:                                                                        
        result = sp.check_output(["ip", "-4", "addr", "show", nic],             
                                                  stderr=sp.STDOUT)
    except Exception:
        return "Unkown NIC: %s" % nic
    result = result.decode().splitlines()
    ipaddr = [l.split()[1].split('/')[0] for l in result if "inet" in l]        
    return ipaddr[0]

De plus, vous pouvez utiliser une approche similaire pour obtenir une liste de cartes réseau:

def get_nics():                                                                 
    """                                                                         
        Get all NICs from the Operating System.                                 

        Returns                                                                 
        -------                                                                 
        nics : list                                                             
            All Network Interface Cards.                                        
    """                                                                         
    result = sp.check_output(["ip", "addr", "show"])                            
    result = result.decode().splitlines()                                       
    nics = [l.split()[1].strip(':') for l in result if l[0].isdigit()]          
    return nics                                                

Voici la solution en tant que Gist .

Et vous auriez quelque chose comme ça:

$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> 
>>> import helpers
>>> 
>>> helpers.get_nics()
['lo', 'enp1s0', 'wlp2s0', 'docker0']
>>> helpers.get_nic_ipv4('docker0')
'172.17.0.1'
>>> helpers.get_nic_ipv4('docker2')
'Unkown NIC: docker2'
0
ivanleoncz

C'est le résultat de ifconfig:

pi@raspberrypi:~ $ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.2.24  netmask 255.255.255.0  broadcast 192.168.2.255
        inet6 fe80::88e9:4d2:c057:2d5f  prefixlen 64  scopeid 0x20<link>
        ether b8:27:eb:d0:9a:f3  txqueuelen 1000  (Ethernet)
        RX packets 261861  bytes 250818555 (239.1 MiB)
        RX errors 0  dropped 6  overruns 0  frame 0
        TX packets 299436  bytes 280053853 (267.0 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<Host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 74  bytes 16073 (15.6 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 74  bytes 16073 (15.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:85:cf:a6  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

pi@raspberrypi:~ $ 

En coupant un peu la sortie, nous avons:

pi@raspberrypi:~ $ 
pi@raspberrypi:~ $ ifconfig eth0 | grep "inet 192" | cut -c 14-25
192.168.2.24
pi@raspberrypi:~ $ 
pi@raspberrypi:~ $ 

Maintenant, nous pouvons aller en python et faire:

import os
mine = os.popen('ifconfig eth0 | grep "inet 192" | cut -c 14-25')
myip = mine.read()
print (myip)
0
Omar Cruz