В настоящее время вы загружаете все сети в память, прежде чем проверять IP-адреса, но вам действительно не нужно это делать, вы можете просто перебирать ваш читатель вместо того, чтобы преобразовывать его в список.
Вместо этого я бы загрузил все IP-адреса, чтобы их проверить в списке и отсортировать. Затем можно использовать bisect
, чтобы получить все IP-адреса из списка, которые находятся в одной сети в логарифмическом времени, поэтому вместо O(m*n)
у вас будет O(m*log(n))
, а также стоимость сортировки списка адресов.
должен быть похож на этот *:
from bisect import bisect_left, bisect_right
def find_ips_in_network(network, sorted_ips):
first = netaddr.IPAddress(network.first)
last = netaddr.IPAddress(network.last)
first_idx = bisect_left(sorted_ips, first)
last_idx = bisect_right(sorted_ips, last)
return sorted_ips[first_idx:last_idx]
sorted_ips = sorted(...) # load ips as sorted list of netaddr.IPAddress
found_networks = dict()
# or collections.defaultdict(list) if you want all networks
with open(r"file.csv", 'rb') as f:
reader = csv.reader(f)
for row in reader:
network = netaddr.IPNetwork(row[0])
for ip in find_ips_in_network(network, sorted_ips):
found_networks[ip] = row
# or found_networks[ip].append(row) if using defaultdict
for ip in sorted_ips:
if ip in found_networks:
print ip, "found in:", found_networks[ip]
* Отказ от ответственности: нет никакой гарантии правильности
Edit: небольшая оптимизация: так как индекс первого адреса вычисляется первым, он может быть использован для ограничить нижний предел при поиске последнего индекса:
last_idx = bisect_right(sorted_ips, last, first_index)
Объяснение:bisect_left
и bisect_right
используйте binary search для поиска отсортированного списка для заданного значения и возврата индекса, в который значение должно быть вставлено, чтобы сохранить сортировку списка. Разница между bisect_left
и bisect_right
- это тот случай, когда значение уже находится в списке (один или несколько раз), bisect_left
вернет индекс первого совпадения, bisect_right
- индекс последнего + 1.
Так что в этом случае:
first_idx = bisect_left(sorted_ips, first)
возвращает индекс первого IPAddress от sorted_ips
, который больше или равен first
и
last_idx = bisect_right(sorted_ips, last, first_idx)
возвращает индекс один после последнего IPAddress меньше или равным last
. Мы знаем, что first <= last
, поэтому fist_idx
должно быть <= last_idx
, поэтому нижняя граница второго поиска может быть ограничена first_idx
.
Это означает, что срез sorted_ips[first_idx:last_idx]
содержит все IP-адреса из списка: first <= ip <= last
. Если ни один из адресов в списке не равен или между first
и last
, оба индекса будут одинаковыми, возвращая пустой список.
Поскольку бинарный поиск имеет наихудший показатель производительности O(log(n))
, это будет значительно быстрее, чтобы найти, какие IP-адреса из списка находятся в сети, а затем проверить все сети для всех IP-адресов, особенно если список IP-адресов для проверки очень большой ,
Я попробую это и сообщите, если это быстрее. Спасибо, что ответили – Con7e
«return sorted_ips [first_idx: last_idx]» всегда возвращает список «sorted_IPs», который я первоначально использовал для поиска в базе данных. Почему это? Меня интересует информация в базе данных, а не мой собственный список. Вы можете помочь? – Con7e
Функция должна возвращать все ips в списке, который находится в данной сети. Насколько я понял, вы пытаетесь найти список IP-адресов, чтобы найти, находятся ли они в одной из сетей вашего csv, правильно ли это или я что-то неправильно понял? Это решение оборачивается этим и проверяет наличие в нем всех сетей, в которых находятся указанные IP-адреса. – mata