¿Cómo puedo encontrar direcciones IP locales (es decir, 192.168.xx o 10.0.xx) en la plataforma Python de forma independiente y usando solo la biblioteca estándar?
fuente
¿Cómo puedo encontrar direcciones IP locales (es decir, 192.168.xx o 10.0.xx) en la plataforma Python de forma independiente y usando solo la biblioteca estándar?
import socket
socket.gethostbyname(socket.gethostname())
Esto no funcionará siempre (regresa 127.0.0.1
en máquinas que tienen el nombre de host /etc/hosts
como 127.0.0.1
), un paliativo sería lo que muestra gimel, use socket.getfqdn()
en su lugar. Por supuesto, su máquina necesita un nombre de host resoluble.
socket.gethostbyname_ex(socket.gethostname())[-1]
Acabo de encontrar esto, pero parece un poco difícil, sin embargo, dicen que lo probé en * nix y lo hice en Windows y funcionó.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
Esto supone que tiene acceso a Internet y que no hay un proxy local.
Este método devuelve la IP "primaria" en el cuadro local (el que tiene una ruta predeterminada) .
Python 3 o 2:
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 Exception:
IP = '127.0.0.1'
finally:
s.close()
return IP
Esto devuelve una única IP que es la principal (la que tiene una ruta predeterminada). Si necesita en su lugar todas las IP conectadas a todas las interfaces (incluido localhost, etc.), consulte esta respuesta .
Si está detrás de un cortafuegos NAT como su caja wifi en casa, entonces esto no mostrará su IP NAT pública, sino su IP privada en la red local que tiene una ruta predeterminada a su enrutador WIFI local; obtener la IP externa de su enrutador wifi requeriría ejecutar esto en ESA caja, o conectarse a un servicio externo como whatismyip.com/whatismyipaddress.com que podría reflejar la IP ... pero eso es completamente diferente de la pregunta original. :)
socket.gethostbyname(socket.gethostname())
da resultados horribles
Como se llama un alias myip
, eso debería funcionar en todas partes:
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])'"
Igual que el anterior, pero solo el código 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])
Versión que también funcionará en LAN sin conexión a 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])
(gracias @ccpizza )
Antecedentes :
El uso socket.gethostbyname(socket.gethostname())
no funcionó aquí, porque una de las computadoras en las que estaba tenía /etc/hosts
entradas duplicadas y referencias a sí misma. socket.gethostbyname()
solo devuelve la última entrada en /etc/hosts
.
Este fue mi intento inicial, que elimina todas las direcciones que comienzan con "127."
:
import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
Esto funciona con Python 2 y 3, en Linux y Windows, pero no se ocupa de varios dispositivos de red o IPv6. Sin embargo, dejó de funcionar en distribuciones recientes de Linux, así que probé esta técnica alternativa. Intenta conectarse al servidor DNS de Google 8.8.8.8
en el puerto 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])
Luego combiné las dos técnicas anteriores en una línea que debería funcionar en todas partes, y creé el myip
alias y el fragmento de Python en la parte superior de esta respuesta.
Con la creciente popularidad de IPv6, y para servidores con múltiples interfaces de red, el uso de un módulo Python de terceros para encontrar la dirección IP es probablemente más robusto y confiable que cualquiera de los métodos enumerados aquí.
socket.getaddrinfo()
debería funcionar de manera consistente en todas las plataformas, pero solo lo comprobé en Linux, no me molesté en ningún otro sistema operativo.
/etc/resolve.conf: No such file or directory
y tengo la dirección IPv4 local mostrada por ifconfig
.
Puede usar el módulo netifaces . Sólo tipo:
pip install netifaces
en su shell de comandos y se instalará en la instalación predeterminada de Python.
Entonces puedes usarlo así:
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))
En mi computadora imprimió:
{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207
El autor de este módulo afirma que debería funcionar en Windows, UNIX y Mac OS X.
Método de API de socket
ver https://stackoverflow.com/a/28950776/711085
Desventajas:
Método de reflector
(Tenga en cuenta que esto no responde a la pregunta del OP sobre la dirección IP local, por ejemplo, 192.168 ...; le da su dirección IP pública, que podría ser más deseable dependiendo del caso de uso).
Puede consultar algún sitio como whatismyip.com (pero con una API), como:
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)
o si usa 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)
Ventajas:
Desventajas (y soluciones):
editar : Aunque inicialmente pensé que estos métodos eran realmente malos (a menos que use muchos fallos, el código puede ser irrelevante dentro de muchos años), plantea la pregunta "¿qué es Internet?". Una computadora puede tener muchas interfaces que apuntan a muchas redes diferentes. Para una descripción más completa del tema, google forgateways and routes
. Una computadora puede acceder a una red interna a través de una puerta de enlace interna, o acceder a la red mundial a través de una puerta de enlace en, por ejemplo, un enrutador (generalmente el caso). La dirección IP local sobre la que pregunta el OP solo está bien definida con respecto a una sola capa de enlace, por lo que debe especificar eso ("¿es de la tarjeta de red o del cable de Ethernet, de lo que estamos hablando?") . Puede haber múltiples respuestas no únicas a esta pregunta como se plantea. Sin embargo, la dirección IP global en la red mundial probablemente esté bien definida (en ausencia de una fragmentación masiva de la red): probablemente la ruta de retorno a través de la puerta de enlace que puede acceder a los TLD.
Si la computadora tiene una ruta a Internet, esto siempre funcionará para obtener la dirección IP local preferida, incluso si / etc / hosts no está configurado correctamente.
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]
8.8.8.8
es un servidor dns de google ¿podemos hacerlo con un servidor dns local?
En 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'
>>>
ioctl
). El socket no está vinculado a la interfaz para la que desea información adicional, es solo un mecanismo de comunicación entre el espacio de usuario y el kernel. en.wikipedia.org/wiki/Ioctl lxr.free-electrons.com/source/net/socket.c
struct.pack('16sH14s', iface, socket.AF_INET, '\x00'*14)
debe reemplazarse construct.pack('16sH14s', iface.encode('utf-8'), socket.AF_INET, b'\x00'*14)
ioctl
es una interfaz heredada que no creo que sea compatible con IPv6 y probablemente nunca lo hará. Creo que la forma 'correcta' es a través de Netlink, que no es muy sencillo en Python. Creo que libc debería tener la función a la getifaddrs
que se puede acceder a través del ctypes
módulo de pitones que puede funcionar - man7.org/linux/man-pages/man3/getifaddrs.3.html
Estoy usando el siguiente módulo:
#!/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
Probado con Windows y Linux (y no requiere módulos adicionales para esos) destinados a su uso en sistemas que se encuentran en una sola LAN basada en IPv4.
La lista fija de nombres de interfaz no funciona para las versiones recientes de Linux, que han adoptado el cambio systemd v197 con respecto a los nombres de interfaz predecibles como lo señala Alexander . En tales casos, debe reemplazar manualmente la lista con los nombres de interfaz en su sistema, o usar otra solución como netifaces .
enp0s25
. Para obtener más información, consulte wiki.archlinux.org/index.php/Network_Configuration#Device_names
struct.pack('256s', bytes(ifname[:15]))
Lo uso en mis máquinas ubuntu:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
Esto no funciona
Si no desea utilizar paquetes externos y no desea confiar en servidores externos de Internet, esto podría ayudar. Es una muestra de código que encontré en Google Code Search y modifiqué para devolver la información requerida:
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
Uso:
>>> for addr in getIPAddresses():
>>> print addr
192.168.0.100
10.5.9.207
Como se basa windll
, esto solo funcionará en Windows.
En Debian (probado) y sospecho que la mayoría de Linux ...
import commands
RetMyIP = commands.getoutput("hostname -I")
En MS Windows (probado)
import socket
socket.gethostbyname(socket.gethostname())
hostname: illegal option -- I\nusage: hostname [-fs] [name-of-host]
Una versión que no creo que haya sido publicada todavía. Probé con python 2.7 en Ubuntu 12.04.
Encontré esta solución en: 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])
Resultado de ejemplo:
>>> get_ip_address('eth0')
'38.113.228.130'
Variación sobre la respuesta de ninjagecko. Esto debería funcionar en cualquier LAN que permita la transmisión UDP y no requiera acceso a una dirección en la LAN o 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())
<broadcast>
un nombre de host válido? ¿Cuántos de estos tipos de nombres de host verbales son válidos?
Me temo que no hay una buena plataforma independiente para hacer esto que no sea conectarse a otra computadora y que le envíe su dirección IP. Por ejemplo: findmyipaddress . Tenga en cuenta que esto no funcionará si necesita una dirección IP que esté detrás de NAT a menos que la computadora a la que se está conectando también esté detrás de NAT.
Aquí hay una solución que funciona en Linux: obtenga la dirección IP asociada con una interfaz de red .
Una forma sencilla de producir resultados "limpios" a través de las utilidades de línea de comandos:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print $2'} | sed -ne 's/addr\:/ /p'")
print ips
Mostrará todas las direcciones IPv4 en el sistema.
FYI puedo verificar que el método:
import socket
addr = socket.gethostbyname(socket.gethostname())
Funciona en OS X (10.6,10.5), Windows XP y en un servidor de departamento RHEL bien administrado. No funcionó en una VM CentOS muy mínima en la que solo hago un poco de pirateo del kernel. Entonces, para esa instancia, solo puede verificar la dirección 127.0.0.1 y, en ese caso, hacer lo siguiente:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
Y luego analiza la dirección IP de la salida. Cabe señalar que ifconfig no está en la RUTA de un usuario normal de forma predeterminada y es por eso que doy la ruta completa en el comando. Espero que esto ayude.
Esta es una variante de la respuesta de UnkwnTech: proporciona una get_local_addr()
función que devuelve la dirección IP de LAN principal del host. Lo estoy publicando porque esto agrega una serie de cosas: soporte de ipv6, manejo de errores, ignorando los agregadores localeshost / linklocal, y usa un complemento TESTNET (rfc5737) para conectarse.
# imports
import errno
import socket
import logging
# 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:
# log.info("trapped error connecting to %r via %r", remote, family, exc_info=True)
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
None
get_local_addr(remove="www.google.com")
regresar? El registro de los socket.error
lanzados por _get_local_addr () podría ayudar en el diagnóstico.
import socket
[i[4][0] for i in socket.getaddrinfo(socket.gethostname(), None)]
['fe80::34e8:fe19:1459:2cde%22','fe80::d528:99fb:d572:e289%12', '192.168.56.1', '192.168.1.2']
en el escritorio de Windows.
Esto funcionará en la mayoría de las cajas de 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()
Esta respuesta es mi intento personal de resolver el problema de obtener la IP de LAN, ya que socket.gethostbyname(socket.gethostname())
también devolvió 127.0.0.1. Este método no requiere Internet, solo una conexión LAN. El código es para Python 3.x pero podría convertirse fácilmente para 2.x. Usando UDP Broadcast:
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
es tu dirección IP real En términos más generales, una computadora puede tener cualquier número de direcciones IP. Puede filtrarlos para redes privadas: 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 y 192.168.0.0/16.
Sin embargo, no hay una forma multiplataforma para obtener todas las direcciones IP. En Linux, puede usar el SIOCGIFCONF
ioctl.
Un ligero refinamiento de la versión de los comandos que usa el comando IP y devuelve las direcciones IPv4 e 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)]
Bueno, puede usar el comando "ip route" en GNU / Linux para conocer su dirección IP actual.
Esto muestra la IP dada a la interfaz por el servidor DHCP que se ejecuta en el enrutador / módem. Por lo general, "192.168.1.1/24" es la IP para la red local, donde "24" significa el rango de posibles direcciones IP proporcionadas por el servidor DHCP dentro del rango de máscara.
Aquí hay un ejemplo: tenga en cuenta que PyNotify es solo una adición para aclarar mi punto y no es obligatorio en absoluto
#! /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()
La ventaja de esto es que no necesita especificar la interfaz de red. Eso es bastante útil cuando se ejecuta un servidor de socket
Puede instalar PyNotify usando easy_install o incluso Pip:
easy_install py-notify
o
pip install py-notify
o dentro de un script / intérprete de Python
from pip import main
main(['install', 'py-notify'])
Si está buscando una dirección IPV4 diferente de su dirección IP localhost 127.0.0.1
, aquí hay una buena pieza de códigos python:
import subprocess
address = subprocess.check_output(['hostname', '-s', '-I'])
address = address.decode('utf-8')
address=address[:-1]
Que también se puede escribir en una sola línea:
address = subprocess.check_output(['hostname', '-s', '-I']).decode('utf-8')[:-1]
Incluso si se pone localhost
en /etc/hostname
el código todavía le dará a su dirección IP local.
Para Linux, puede usar check_output
el hostname -I
comando del sistema de la siguiente manera:
from subprocess import check_output
check_output(['hostname', '-I'])
Nota: Esto no está usando la biblioteca estándar, pero es bastante simple.
$ pip instalar pif
from pif import get_public_ip
get_public_ip()
netifaces está disponible a través de pip y easy_install. (Lo sé, no está en la base, pero podría valer la pena la instalación).
netifaces tiene algunas rarezas entre plataformas:
Aquí hay un código de netifaces para jugar:
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.
El código anterior no asigna una dirección a su nombre de interfaz (útil para generar reglas de ebtables / iptables sobre la marcha). Así que aquí hay una versión que mantiene la información anterior con el nombre de la interfaz en una tupla:
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]
Y no, no estoy enamorado de las listas de comprensión. Es la forma en que funciona mi cerebro en estos días.
El siguiente fragmento lo imprimirá todo:
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)
¡Disfrutar!
Una versión de Python 3.4 que utiliza el paquete asyncio recientemente introducido.
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
Esto se basa en la excelente respuesta de UnkwnTech .
Para obtener la dirección IP, puede usar un comando de shell directamente en 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()
ifconfig -a
y usar la salida de allí ...ip addr
es mucho más adecuado (y más fácil de analizar, arrancar).bind
un socket a una interfaz particular, entonces es una cuestión de política. Si se necesita la dirección IP local para entregarla a un par para que el par pueda "devolver la llamada", es decir, para abrir una conexión de nuevo a la máquina local, entonces la situación depende de si hay alguna NAT (traducción de dirección de red) cajas en el medio. Si no hay NAT,getsockname
es una buena opción.