¿Cómo puedo obtener la dirección IP de eth0 en Python?

Cuando se produce un error en un script de Python en Unix, se envía un correo electrónico.

Se me ha pedido que agregue {Ambiente de prueba} a la línea de asunto del correo electrónico si la dirección IP es 192.168.100.37, que es el servidor de prueba. De esta manera podemos tener una versión de un script y una forma de saber si el correo electrónico proviene de datos desordenados en el servidor de prueba.

Sin embargo, cuando busco en Google, sigo encontrando este código:

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

Sin embargo, eso me está dando la dirección IP de 127.0.1.1. Cuando uso ifconfig obtengo esto

 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) 

En primer lugar, no sé de dónde salió el 127.0.1.1, pero de cualquier manera eso no es lo que quiero. Cuando busco en Google, sigo llegando a la misma syntax, Bash scripts o netifaces y estoy tratando de usar bibliotecas estándar.

Entonces, ¿cómo puedo obtener la dirección IP de eth0 en Python?

Dos métodos:

Método # 1 (usar paquete externo)

Debe solicitar la dirección IP que está vinculada a su interfaz eth0 . Esto está disponible en el paquete de 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" 

También puede obtener una lista de todas las interfaces disponibles a través de

 ni.interfaces() 

Método # 2 (sin paquete externo)

Aquí hay una forma de obtener la dirección IP sin usar un paquete de 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' 

Nota: la detección de la dirección IP para determinar el entorno que está utilizando es un truco. Casi todos los marcos proporcionan una forma muy sencilla de configurar / modificar una variable de entorno para indicar el entorno actual. Intente y eche un vistazo a su documentación para esto. Debe ser tan simple como hacer

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

Alternativamente, si desea obtener la dirección IP de la interfaz que se utiliza para conectarse a la red sin tener que saber su nombre, puede usar esto:

 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] 

Sé que es un poco diferente a tu pregunta, pero otros pueden llegar aquí y encontrar esta más útil. No es necesario tener una ruta a 8.8.8.8 para usar esto. Todo lo que está haciendo es abrir un socket, pero no enviar ningún dato.

Un enfoque simple que devuelve una cadena con direcciones ip para las interfaces es:

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

para más información ver nombre de host .

Si solo necesita trabajar en Unix, puede usar una llamada del sistema (ref. Pila de desbordamiento de pregunta Parse ifconfig para obtener solo mi dirección IP usando Bash ):

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

Dado que la mayoría de las respuestas utilizan ifconfig para extraer el IPv4 de la interfaz eth0, que está en desuso a favor de ip addr , se podría usar el siguiente código:

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

ACTUALIZAR:

Alternativamente, puedes cambiar parte de la tarea de análisis al intérprete de python usando split() lugar de grep y awk, como @serg señala en el comentario:

 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] 

Pero en este caso, debe verificar los límites de la matriz devuelta por cada llamada split() .

ACTUALIZACIÓN 2:

Otra versión usando 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] 

Prueba el siguiente código, funciona para mí en Mac10.10.2:

 import subprocess if __name__ == "__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 

Sobre la base de la respuesta de @jeremyjjbrown, otra versión que se limpia después de sí misma como se menciona en los comentarios a su respuesta. Esta versión también permite proporcionar una dirección de servidor diferente para su uso en redes internas privadas, 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] 

Funciono para mi

  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 

Encuentre la dirección IP de la primera entrada eth / wlan en ifconfig que está EN EJECUCIÓN:

 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