#python #ip-address #python-ipaddress
Вопрос:
Я ищу способ зацикливания на определенных хостах, отфильтрованных по частичному суффиксу. Поскольку сети ipv6 огромны, моя фактическая реализация требует много времени и поиска наилучшего решения для достижения того же результата.
Это пример моего реального теста для достижения того, что мне нужно :
import ipaddress
from itertools import islice
for address, suffix in zip(['10.10.0.0/16','2A00:7E40:F020::/64'],['.1',':00FF:FE00:0003']):
print('===============')
network = ipaddress.ip_network(address)
print(str(network.num_addresses) ' addresses available')
print('suffix ' suffix)
print('===============')
for ip in islice(filter(lambda x: str(x.exploded).endswith(suffix),network.hosts()),0,2):
print(ip)
Фактический объем производства :
===============
65536 addresses available
suffix .1
===============
10.10.0.1
10.10.1.1
===============
18446744073709551616 addresses available
suffix :00FF:FE00:0003
===============
^C
С уважением,
Комментарии:
1. В чем здесь проблема? Несмотря на то, что пространство поиска огромно, я сомневаюсь, что вы затрудняете фильтрацию итерации. Вы ищете более быстрый итератор, или более быстрый способ что-то сделать с этими ip-адресами, когда они у вас есть, или что-то совсем другое?
2. Проблема заключается во времени, которое требуется, поскольку ip-адрес не обеспечивает «оптимизированный» способ сделать это. Не уверен, что более быстрый итератор будет достаточно быстрым. Может быть, есть лучший способ найти все IP-адреса из cidr с определенным суффиксом без ретрансляции на итераторе .hosts ()?
Ответ №1:
Пытаясь понять, как ускорить фильтрацию и нарезку, я пришел к этому решению, которое, похоже, справляется с этой задачей довольно быстро, даже если мы начнем с середины огромного блока IPV6
#!/usr/bin/env python3
import ipaddress
from itertools import islice
def newv6hosts(self,start=None,limit=None,suffix=None):
# - start is the index of the ip from where we should start
# - limit is the number of ip we want
# - if suffix is specified, only ips respecting this suffix will be
# generated. start / limit will be updated to corresponding to the index
# of thoses ip.
range_start = int(self.network_address) 1
range_end = int(self.broadcast_address)
range_step = 1
if suffix:
if suffix.find('::') != -1:
raise ValueError('Suffix should not contain "::"')
suffix_address = ipaddress.ip_address(''.join([str(self.network_address),suffix]))
if int(suffix_address) < int(self.network_address):
raise ValueError('Suffix index is lower than Network adress')
suffix_len = len(suffix.replace(':',''))
range_start = int(suffix_address)
range_step = 16 ** suffix_len
if start:
new_start = range_start (start * int(range_step or 1))
if new_start < range_end:
range_start = new_start
else:
range_start = range_end
if limit:
new_end = range_start (limit * int(range_step or 1))
if new_end < range_end:
range_end = new_end
for x in range(range_start, range_end, range_step):
yield self._address_class(x)
# Replace default method to :
# - have a start / limit without relaying on islice (faster)
# - filter ips generated based on a suffix
ipaddress.IPv6Network.hosts = newv6hosts
for address, suffix in zip(['10.10.0.0/16','2A00:7E40:F020::/64'],['.1','00FF:FE00:0003']):
print('===============')
network = ipaddress.ip_network(address)
print(str(network.num_addresses) ' addresses available')
print('suffix ' suffix)
print('===============')
if network.version == 4:
for ip in islice(filter(lambda x: str(x.exploded).endswith(suffix),network.hosts()),0,2):
print(ip)
else:
for ip in network.hosts(start=500,limit=2,suffix=suffix):
print(ip)
Выход :
===============
65536 addresses available
suffix .1
===============
10.10.0.1
10.10.1.1
===============
18446744073709551616 addresses available
suffix 00FF:FE00:0003
===============
2a00:7e40:f020:0:1f4:ff:fe00:3
2a00:7e40:f020:0:1f5:ff:fe00:3