Python—计算IP范围内IP的最佳方法

Python—计算IP范围内IP的最佳方法,python,python-2.7,ip,Python,Python 2.7,Ip,我有一个python脚本,它从arp表中获取所有IP并将其分配给一个变量。我有一个for循环,它创建了另外两个变量start_IP(包含子网的第一个IP)和last_IP(包含同一子网的最后一个IP)。对于每个循环,我将有一个不同的开始和最后的IP 我试图检查包含所有IP的变量,看看每个子网下有多少IP 最好的方法是什么?下面是一个硬编码示例: 计数=0 arps = ['10.20.30.130','10.20.30.131','10.20.30.132', '10.20.30.133',

我有一个python脚本,它从arp表中获取所有IP并将其分配给一个变量。我有一个for循环,它创建了另外两个变量start_IP(包含子网的第一个IP)和last_IP(包含同一子网的最后一个IP)。对于每个循环,我将有一个不同的开始和最后的IP

我试图检查包含所有IP的变量,看看每个子网下有多少IP

最好的方法是什么?下面是一个硬编码示例: 计数=0

arps = ['10.20.30.130','10.20.30.131','10.20.30.132', '10.20.30.133', 
'10.20.30.136', '10.20.30.137', '10.20.30.138', '10.20.30.139', '10.20.30.140', '10.20.30.141', '10.20.30.143', '10.20.30.149']
 start_ip = "10.20.30.132"
 end_ip = "10.20.30.142"
 count = 0      
 for arp in arps:
    if arp >= start_ip and arp <= end_ip:
        count = count + 1
        print count
    else:
        continue

 print "Count: ", count
arps=['10.20.30.130'、'10.20.30.131'、'10.20.30.132'、'10.20.30.133',
'10.20.30.136', '10.20.30.137', '10.20.30.138', '10.20.30.139', '10.20.30.140', '10.20.30.141', '10.20.30.143', '10.20.30.149']
开始\u ip=“10.20.30.132”
end_ip=“10.20.30.142”
计数=0
对于arp中的arp:

如果arp>=启动ip和arp两种方式。简单的方法是:

IP地址逐八位字节进行比较。有趣的是,Python列出了逐个元素的比较。因此,如果您只需按点拆分IP地址并将列表映射到
int
,就可以正确地比较它们

更简单的方法是:

ipaddress.ip\u地址
是可比较的,只要比较的地址是相同的版本(IPv4或IPv6)

但是,字符串比较不能提供IP地址的正确顺序:

'1.12.1.1' < '1.2.1.1'
# => True (should be False)

我可以想到以下两种解决方案。方法1的时间复杂度为
O(N)
,方法2的时间复杂度为
O(nlogn)
。正如Amadan所建议的,IP地址需要事先进行预处理

import bisect

arps = ['10.20.30.130','10.20.30.131','10.20.30.132', '10.20.30.133', 
'10.20.30.136', '10.20.30.137', '10.20.30.138', '10.20.30.139', '10.20.30.140', '10.20.30.141', '10.20.30.143', '10.20.30.149']
start_ip = "10.20.30.132"
end_ip = "10.20.30.142"

# Padding zeros to the IP addresses to make sure they are directly comparable
def padding(s):
    return s.zfill(3)

arps = [".".join(list(map(padding, x.split(".")))) for x in arps]
start_ip = ".".join(list(map(padding, start_ip.split("."))))
end_ip   = ".".join(list(map(padding, end_ip.split("."))))

# Method 1: Pythonic one-liner
print(sum(start_ip <= x <= end_ip for x in arps))

# Method 2: Sort and binary search
def find_lt(a, x):
    i = bisect.bisect_right(a, x)
    if i:
        return i - 1
    else:
        return 0

def find_gt(a, x):
    i = bisect.bisect_right(a, x)
    if i != len(a):
        return i
    else:
        return i

arps.sort()
print(find_gt(arps, end_ip) - find_lt(arps, start_ip))
导入对分 arps=['10.20.30.130'、'10.20.30.131'、'10.20.30.132'、'10.20.30.133', '10.20.30.136', '10.20.30.137', '10.20.30.138', '10.20.30.139', '10.20.30.140', '10.20.30.141', '10.20.30.143', '10.20.30.149'] 开始\u ip=“10.20.30.132” end_ip=“10.20.30.142” #将零填充到IP地址以确保它们直接可比 def填充: 返回s.zfill(3) arps=[“.”.join(在arps中x的列表(映射(填充,x.split(“.”))) start_ip=“.”join(列表(映射(填充,start_ip.split(“.”))) end_ip=“.”连接(列表(映射(填充,end_ip.split(“.”))) #方法1:肾盂一衬
print(sum)(start_ip)这是不正确的,因为我在回答中解释了一个问题-
sort
不会按正确的顺序对字符串ip进行排序。@Amadan是的,你是对的。让我来说明一个解决方法。另外,如果忽略排序的事实,方法2的复杂性为O(logn)。排序本身就是O(logn)。(当然,big-O不是速度的度量,只是复杂性…@Amadan-True。谢谢。现在呢?它会起作用的,尽管我认为
list(map(int,x.split(“.”))
”简单得多,也快得多。join(list(map(padding,x.split(“.”)))
。我的数据库中确实有CIDR,因此您的上一个解决方案可能会工作得很好,并尽量减少代码。我会尝试一下!谢谢。我将使用第一个解决方案。我使用的是python 2,因此我必须先将所有IP字符串转换为Unicode才能使其工作。
ipaddress.ip_address('192.168.1.17') in ipaddress.ip_network('192.168.0.0/16')
# => True
import bisect

arps = ['10.20.30.130','10.20.30.131','10.20.30.132', '10.20.30.133', 
'10.20.30.136', '10.20.30.137', '10.20.30.138', '10.20.30.139', '10.20.30.140', '10.20.30.141', '10.20.30.143', '10.20.30.149']
start_ip = "10.20.30.132"
end_ip = "10.20.30.142"

# Padding zeros to the IP addresses to make sure they are directly comparable
def padding(s):
    return s.zfill(3)

arps = [".".join(list(map(padding, x.split(".")))) for x in arps]
start_ip = ".".join(list(map(padding, start_ip.split("."))))
end_ip   = ".".join(list(map(padding, end_ip.split("."))))

# Method 1: Pythonic one-liner
print(sum(start_ip <= x <= end_ip for x in arps))

# Method 2: Sort and binary search
def find_lt(a, x):
    i = bisect.bisect_right(a, x)
    if i:
        return i - 1
    else:
        return 0

def find_gt(a, x):
    i = bisect.bisect_right(a, x)
    if i != len(a):
        return i
    else:
        return i

arps.sort()
print(find_gt(arps, end_ip) - find_lt(arps, start_ip))