ipaddress - python get ip address
Cómo obtener la dirección IP de la interfaz física desde una interfaz (3)
Lo que he hecho hasta ahora, usando clases de PyQt:
all_Addresses = QNetworkInterface.allAddresses() #list-of-QHostAddress
for addr in all_Addresses:
print(addr.toString())
Salida:
172.16.0.186 - Virtual Interface IP address
192.168.10.2 - Physical interface IP address. I want this one.
127.0.0.1
Utilizando socket
import socket
print(socket.gethostbyname(socket.gethostname()))
Salida:
172.16.0.186 - When openVPN is on
192.168.10.2 - When its off
- ¿Hay alguna forma de distinguirlos?
- ¿Se puede hacer esto con Python ordinario, en lugar de usar clases de PyQt?
- ¿Cómo puedo obtener la dirección IPv6 también?
Usted debe utilizar los netifaces . Está diseñado para ser multiplataforma y contiene código especializado para Windows junto con una variedad de versiones genéricas que funcionan en diferentes plataformas similares a UNIX / UNIX.
A partir de la versión 0.10.0 de Netifaces, Python3 es compatible.
Resumen de uso
>>> from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
>>> import netifaces as ni
>>> ni.interfaces()
[''lo'', ''eth0'', ''eth1'', ''vboxnet0'', ''dummy1'']
>>>
>>> ni.ifaddresses(''eth0'')[AF_LINK] # NOTE: AF_LINK is an alias for AF_PACKET
[{''broadcast'': ''ff:ff:ff:ff:ff:ff'', ''addr'': ''00:02:55:7b:b2:f6''}]
>>> ni.ifaddresses(''eth0'')[AF_INET]
[{''broadcast'': ''172.16.161.7'', ''netmask'': ''255.255.255.248'', ''addr'': ''172.16.161.6''}]
>>>
>>> # eth0 ipv4 interface address
>>> ni.ifaddresses(''eth0'')[AF_INET][0][''addr'']
''172.16.161.6''
>>>>
Detalles
Soporte de Windows:
No se requiere compilador para la mayoría de las instalaciones de MS Windows. Si recibe advertencias sobre la instalación de MS Visual C ++ para Windows, tenga mucho cuidado, ya que debe hacer coincidir la versión del compilador que usó Python con la que usó para el módulo.
Ejemplo detallado de estructuras de datos de netifaces :
>>> import netifaces as ni
>>> ni.interfaces()
[''lo'', ''eth0'', ''eth1'', ''vboxnet0'', ''dummy1'']
>>> ni.ifaddresses(''eth0'')
{
17: [
{
''broadcast'': ''ff:ff:ff:ff:ff:ff'',
''addr'': ''00:02:55:7b:b2:f6''
}
],
2: [
{
''broadcast'': ''172.16.161.7'',
''netmask'': ''255.255.255.248'',
''addr'': ''172.16.161.6''
}
],
10: [
{
''netmask'': ''ffff:ffff:ffff:ffff::'',
''addr'': ''fe80::202:55ff:fe7b:b2f6%eth0''
}
]
}
>>>
>>> print(ni.ifaddresses.__doc__)
Obtain information about the specified network interface.
Returns a dict whose keys are equal to the address family constants,
e.g. netifaces.AF_INET, and whose values are a list of addresses in
that family that are attached to the network interface.
>>>
>>> # for the IPv4 address of eth0
>>> ni.ifaddresses(''eth0'')[2][0][''addr'']
''172.16.161.6''
Los números utilizados para indexar protocolos son de /usr/include/linux/socket.h
(en Linux) ... EDITAR : mi kernel 3.2 los tiene aquí: /usr/src/linux-headers-3.2.0-4-common/include/linux/socket.h
#define AF_INET 2 /* Internet IP Protocol */
#define AF_INET6 10 /* IP version 6 */
#define AF_PACKET 17 /* Packet family */
La buena noticia es que no tiene que recordar todas esas constantes de encabezado, se incluyen con los netifaces en netifaces :
>>> from netifaces import AF_INET, AF_INET6, AF_LINK, AF_PACKET, AF_BRIDGE
>>> import netifaces as ni
Utiliza el ioctl SIOCGIFADDR de Linux para encontrar la dirección IP asociada con una interfaz de red, dado el nombre de esa interfaz, por ejemplo, " eth0
". La dirección se devuelve como una cadena que contiene un quad punteado.
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(''lo'')
''127.0.0.1''
>>> get_ip_address(''eth0'')
''38.113.228.130''
Yo uso esta solución. En realidad, es un poco complicado y solo funciona en la familia Linux.
import commands
intf = ''eth0''
intf_ip = commands.getoutput("ip address show dev " + intf).split()
intf_ip = intf_ip[intf_ip.index(''inet'') + 1].split(''/'')[0]
print intf_ip
Esos códigos utilizan el comando ip
en el sistema operativo de la familia linux. Dividió la salida del comando ip
y solo tomó la dirección IPv4 de esas interfaces. Puede cambiar el valor intf
a eth1
o p2p1
.