Поиск локальных IP-адресов с помощью stdlib Python
Как я могу найти локальные IP-адреса (т. е. 192.168.X. x или 10.0.X. x) в платформе Python самостоятельно и с использованием только стандартной библиотеки?
30 ответов
import socket
socket.gethostbyname(socket.gethostname())
Это не будет работать всегда (возвращает 127.0.0.1
на машинах, имеющих имя в /etc/hosts
as 127.0.0.1
), а paliative будет то, что гимель показывает, используйте . Конечно, вашей машине нужно разрешимое имя хоста.
Я только что нашел это, но это кажется немного взломанным, однако они говорят, что попробовали его на *nix, и я сделал на windows, и это сработало.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
print(s.getsockname()[0])
s.close()
предполагается, что у вас есть доступ в интернет и что нет локального прокси-сервера.
как псевдоним называется myip
, это должно работать везде:
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])'"
- работает правильно с Python 2.x, Python 3.X, современные и старые дистрибутивы Linux, OSX / macOS и Windows для поиска текущего адреса IPv4.
- не вернет правильный результат для машин с несколькими IP-адресами, IPv6, без настроенного IP-адреса или без доступа в интернет.
то же, что и выше, но только 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])
- это вызовет исключение, если IP-адрес не настроен.
версия, которая также будет работать на LANs без подключения к интернету:
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])
(спасибо @ccpizza)
фон:
используя socket.gethostbyname(socket.gethostname())
не работал здесь, потому что один из компьютеров, на котором я был, имел /etc/hosts
дублирующие записи и ссылки на себя. socket.gethostbyname()
возвращает только последнюю запись в /etc/hosts
.
это была моя первая попытка, которая отсеивает все адреса, начиная с "127."
:
import socket
print([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])
это работает с Python 2 и 3, на Linux и Windows, но не имеет дело с несколькими сетевыми устройствами или IPv6. Однако он перестал работать на последних дистрибутивах Linux,поэтому я попробовал этот альтернативный метод. Он пытается подключиться к DNS-серверу Google по адресу 8.8.8.8
в порт 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])
затем я объединил два вышеуказанных метода в один лайнер, который должен работать везде, и создал myip
псевдоним и фрагмент Python в верхней части этого ответа.
С ростом популярности IPv6 и для серверов с несколькими сетевыми интерфейсами использование стороннего модуля Python для поиска IP-адреса, вероятно, является более надежным и надежным, чем любой из перечисленных здесь методов.
этот метод возвращает "основной" IP-адрес в локальном поле (с маршрутом по умолчанию).
- не требуется маршрутизируемый сетевой доступ или любое соединение вообще.
- работает, даже если все интерфейсы отключены от сети.
- не нужно и даже не пытаться получить нигде.
- работает с NAT, публичными, частными, внешними и внутренними IP-адресами
- чистый Python 2 (или 3) без внешнего зависимости.
- работает в Linux, Windows и OSX.
Python 2 или 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
Это возвращает один IP-адрес, который является основным (с маршрутом по умолчанию). Если вам нужны все IP-адреса, подключенные ко всем интерфейсам (включая localhost и т. д.), см. ответ.
Если вы находитесь за брандмауэром NAT, как ваш wifi box дома, то это не покажет ваш публичный NAT IP, но вместо вашего частного NAT IP на локальном сеть, которая имеет маршрут по умолчанию к локальному маршрутизатору WIFI; получение внешнего IP-адреса маршрутизатора wifi потребует либо запуска этого на этом поле, либо подключения к внешней службе, такой как whatismyip.com/whatismyipaddress.com это может отражать IP-адрес... но это полностью отличается от первоначального вопроса. :)
обновленный вызов connect () в соответствии с предложением Педро в комментариях. (Если вам нужна конкретная лицензия, это общественное достояние / бесплатно для любого использования, или MIT / CC2-BY-SA на лицензию кода/содержимого переполнения стека по вашему выбору.)
можно использовать netifaces модуль. Просто введите:
pip install netifaces
в вашей командной оболочке, и он установит себя на установку Python по умолчанию.
тогда вы можете использовать его следующим образом:
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))
на моем компьютере она напечатала:
{45639BDC-1050-46E0-9BE9-075C30DE1FBC}: 192.168.0.100 {D43A468B-F3AE-4BF9-9391-4863A4500583}: 10.5.9.207
автор этого модуля утверждает, что он должен работать на Windows, UNIX и Mac OS X.
метод API сокета
см.https://stackoverflow.com/a/28950776/711085
минусы:
- не кросс-платформенный.
- требуется больше резервного кода, привязанного к наличию определенных адресов в интернете
- это также не будет работать, если вы находитесь за NAT
- вероятно, создает UDP-соединение, не независимо от (обычно ISP) доступности DNS (см. другие ответы на такие идеи, как использование 8.8.8.8: сервер Google (по совпадению также DNS))
- убедитесь, что адрес назначения недоступен, например числовой IP-адрес, который гарантированно не используется. Не используйте какой-либо домен, например fakesubdomain.google.com или somefakewebsite.com; вы все равно будете спамом этой партии (сейчас или в будущем) и спамом своих собственных сетевых ящиков.
отражатель метод
(обратите внимание, что это не отвечает на вопрос OP о локальном IP-адресе, например 192.168...; это дает вам ваш публичный IP-адрес, который может быть более желательным в зависимости от варианта использования.)
вы можете запросить какой-то сайт, как whatismyip.com (но с API), например:
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)
или при использовании 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)
плюсы:
- одним из преимуществ этого метода является кросс-платформы
- он работает из-за уродливых NATs (например, ваш домашний маршрутизатор).
недостатки (и их решения):
- требует, чтобы этот сайт был вверх, формат не изменится (почти наверняка не будет), и ваши DNS-серверы будут работать. Можно уменьшить эту проблему, также запросив другие сторонние отражатели IP-адресов в случае сбоя.
- возможный вектор атаки, если вы не запрашиваете несколько отражателей (чтобы предотвратить скомпрометированный отражатель от сообщения вам, что ваш адрес-это то, чего нет), или если вы не используете HTTPS (чтобы предотвратить атаку человека в середине, притворяющегося сервером)
редактировать: хотя первоначально я думал, что эти методы были действительно плохими (если вы не используете много запасных вариантов, код может быть неактуальным через много лет), он ставит вопрос "Что такое интернет?". Компьютер может иметь много интерфейсов, указывающих на множество различных сетей. Для более тщательного описания тема, Google для gateways and routes
. Компьютер может иметь доступ к внутренней сети через внутренний шлюз или доступ к всемирной паутине через шлюз, например, на маршрутизаторе (обычно это так). Локальный IP-адрес, о котором спрашивает OP, хорошо определен только в отношении одного уровня связи, поэтому вы должны указать это ("это сетевая карта или кабель ethernet, о котором мы говорим?"). На этот вопрос может быть несколько неидеальных ответов. Однако глобальный IP адрес во всемирной паутине, вероятно, четко определен (в отсутствие массовой фрагментации сети): вероятно, обратный путь через шлюз, который может получить доступ к дву.
Если у компьютера есть маршрут в интернет, это будет всегда работа для получения предпочтительного локального ip-адреса, даже если /etc/hosts установлен неправильно.
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]
В 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'
>>>
im, используя следующие модули:
#!/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
протестировано с windows и linux (и не требует дополнительных модулей для тех) предназначен для использования в системах, которые находятся в одной локальной сети на основе IPv4.
фиксированный список имен интерфейсов не работает для последних версий linux, которые приняли изменение systemd v197 относительно предсказуемых имен интерфейсов, как указано Александр. В таких случаях необходимо вручную заменить список с имена интерфейсов в вашей системе или используйте другое решение, например netifaces.
Я использую это на своих машинах ubuntu:
import commands
commands.getoutput("/sbin/ifconfig").split("\n")[1].split()[1][5:]
Это не сработает.
Если вы не хотите использовать внешние пакеты и не хотите полагаться на внешние интернет-серверы, это может помочь. Это образец кода, который я нашел на Поиск Кода Google и изменен, чтобы вернуть необходимую информацию:
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
использование:
>>> for addr in getIPAddresses():
>>> print addr
192.168.0.100
10.5.9.207
как он полагается на windll
, это будет работать только на Windows.
на Debian (проверено), и я подозреваю, что большинство Linux..
import commands
RetMyIP = commands.getoutput("hostname -I")
на MS Windows (протестировано)
import socket
socket.gethostbyname(socket.gethostname())
версия, я не считаю, что это было опубликовано еще. Я тестировал с python 2.7 на Ubuntu 12.04.
найдено это решение по адресу : 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])
Пример Результата:
>>> get_ip_address('eth0')
'38.113.228.130'
Я боюсь, что нет никаких хороших независимых от платформы способов сделать это, кроме подключения к другому компьютеру и отправки им вашего IP-адреса. Например: findmyipaddress. Обратите внимание, что это не сработает, если вам нужен IP-адрес, который находится за NAT, если компьютер, к которому вы подключаетесь, также находится за NAT.
вот одно решение, которое работает в Linux: получить IP-адрес, связанный с сетевым интерфейсом.
один простой способ получения "чистого" вывода через utils командной строки:
import commands
ips = commands.getoutput("/sbin/ifconfig | grep -i \"inet\" | grep -iv \"inet6\" | " +
"awk {'print '} | sed -ne 's/addr\:/ /p'")
print ips
он покажет все адреса IPv4 в системе.
FYI я могу проверить, что метод:
import socket
addr = socket.gethostbyname(socket.gethostname())
работает в OS X (10.6,10.5), Windows XP и на хорошо управляемом сервере отдела RHEL. Он не работал на очень минимальной виртуальной машине CentOS, на которой я просто взламываю ядро. Поэтому для этого экземпляра вы можете просто проверить адрес 127.0.0.1 и в этом случае сделать следующее:
if addr == "127.0.0.1":
import commands
output = commands.getoutput("/sbin/ifconfig")
addr = parseaddress(output)
а затем проанализируйте ip-адрес из выходных данных. Следует отметить, что ifconfig по умолчанию не находится в пути обычного пользователя и вот почему я даю полный путь в команде. Надеюсь, это поможет.
Это вариант ответа UnkwnTech - он предоставляет get_local_addr()
функция, которая возвращает основной IP-адрес LAN хоста. Я публикую его, потому что это добавляет ряд вещей: поддержка ipv6, обработка ошибок, игнорирование localhost/linklocal addrs и использует Testnet addr (rfc5737) для подключения.
# 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
Это будет работать на большинстве ящиков 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()
вариация ответа ninjagecko. Это должно работать на любой локальной сети, которая позволяет UDP трансляции и не требует доступа к адресу в локальной сети или интернете.
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())
этот ответ-моя личная попытка решить проблему получения LAN IP, так как socket.gethostbyname(socket.gethostname())
также возвращено 127.0.0.1. Этот метод не требует Интернет только подключение к локальной сети. Код предназначен для Python 3.x, но может быть легко преобразован для 2.X. Использование 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
is ваш реальный IP-адрес. Вообще говоря, компьютер может иметь любое количество IP-адреса. Вы можете фильтровать их для частных сетей - 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12 и 192.168.0.0/16.
однако нет кросс-платформенного способа получить все IP-адреса. В Linux вы можете использовать SIOCGIFCONF
ioctl.
небольшое уточнение версии команд, которая использует команду IP и возвращает адреса IPv4 и 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)]
Ну вы можете использовать команду "ip route" на GNU/Linux, чтобы узнать свой текущий IP-адрес.
Это показывает IP, данный интерфейсу сервером DHCP, работающим на маршрутизаторе / модеме. Обычно" 192.168.1.1/24 "- это IP для локальной сети, где " 24 " означает диапазон возможных IP-адресов, заданных DHCP-сервером в диапазоне масок.
вот пример: обратите внимание, что PyNotify-это просто дополнение, чтобы получить мою точку зрения прямо и не требуется в все!--5-->
#! /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()
преимущество этого заключается в том, что вам не нужно указать сетевой интерфейс. Это очень полезно при запуске сервера сокетов
вы можете установить PyNotify с помощью easy_install или даже Pip:
easy_install py-notify
или
pip install py-notify
или в скрипте/интерпретаторе python
from pip import main
main(['install', 'py-notify'])
netifaces доступен через pip и easy_install. (Я знаю, это не в базе, но это может стоить установки.)
netifaces имеет некоторые странности на разных платформах:
- интерфейс localhost/loop-back не всегда может быть включен (Cygwin).
- адреса перечислены на протокол (например, IPv4, IPv6), а протоколы перечислены на интерфейс. В некоторых системах (Linux) каждая пара протокол-интерфейс имеет свой собственный связанный интерфейс (используя interface_name: N notation), в то время как в других системах (Windows) один интерфейс будет иметь список адресов для каждого протокола. В обоих случаях существует список протоколов, но он может содержать только один элемент.
вот некоторые netifaces код, чтобы играть с:
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.
приведенный выше код не сопоставляет адрес с именем интерфейса (полезно для генерации правил ebtables / iptables на лету). Итак, вот версия, которая сохраняет вышеуказанную информацию с помощью имя интерфейса в кортеже:
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]
и, нет, я не влюблен в понимание списка. Просто мой мозг работает именно так.
следующий фрагмент распечатает все это:
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)
наслаждайтесь!
получить IP-адрес вы можете использовать командная оболочка непосредственно в python:
import socket, subprocess
def getIpAndHostname():
hostname = socket.gethostname()
shell_cmd = "ifconfig | awk '/inet addr/{print substr(,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()
мне пришлось решить проблему "выяснить, является ли IP-адрес локальным или нет", и моей первой мыслью было создать список IP-адресов, которые были локальными, а затем соответствовать ему. Вот что привело меня к этому вопросу. Однако позже я понял, что есть более прямой способ сделать это: попробуйте привязать этот IP-адрес и посмотреть, работает ли он.
_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
Я знаю, что это не отвечает на вопрос напрямую, но это должно быть полезным для тех, кто пытается решить вопрос, а кто был следуя той же мысли. Это имеет то преимущество, что является кросс-платформенным решением (я думаю).
Примечание: это не использует стандартную библиотеку, но довольно просто.
$ pip установить pif
from pif import get_public_ip
get_public_ip()
import netifaces as ni
ni.ifaddresses('eth0')
ip = ni.ifaddresses('eth0')[ni.AF_INET][0]['addr']
print(ip)
это вернет вам IP-адрес в системе Ubuntu, а также MacOS. Выходом будет системный IP-адрес, как и мой IP: 192.168.1.10.