Python 中的 ipaddress 模块如何处理 IP
How ipaddress module in Python handles IPs
我被要求做一个应用程序来提供子网可能的主机总数,遗憾的是我不能使用 Python 提供的 ipaddress
模块所以我需要编写自己的方法来检查和验证输入的数据
我的代码是这样的:
def IP_Validation(chk_IP_vaild):
if chk_IP_vaild.count(".") == 3 and all(isIP(i) for i in chk_IP_vaild.split(".")):
return True
return False
def isIP(IP_String):
try:
return str(int(IP_String)) == IP_String and 0 <= int(IP_String) <= 255
except:
return False
def Calc_Networks(IP_One , IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
print (IP_One,IP_Two)
else:
print ("There is an error")
Calc_Networks("172.11.254.1", "172.1.254.")
Calc_Networks("172.11.254.1", "172.1.254.0")
输出
There is an error
172.11.254.1 172.1.254.0
但这只检查输入的 IP 是否为 IPv4,所以我在网上搜索和检查解决方案,我遇到了这个:
import ipaddress
def calc_inclusive_subnet(ip1, ip2): #accepts 2 IP strings
#make IP Address objects
ip1_obj=ipaddress.IPv4Address(ip1)
ip2_obj=ipaddress.IPv4Address(ip2)
if ip1_obj<=ip2_obj:
min_ip=ip1_obj
max_ip=ip2_obj
else:
min_ip=ip2_obj
max_ip=ip1_obj
distance = int(max_ip)-int(min_ip) #**
return distance
print (calc_inclusive_subnet("192.168.1.0", "192.168.2.255"))
输出
511
我注意到,如果我对使用 ipaddress
模块声明的两个 IP 进行减法运算,它会毫无问题地正确执行,因此我转到 Docs 以了解该模块如何处理IP,所以我可以使用类似的方法
使用 代码 1 进行减法会出现以下错误:
def Calc_Networks(IP_One , IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
dis = int(IP_Two) - int(IP_One)
return dis
输出为:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-154-9e53188ce6f1> in <module>
16
17
---> 18 print(Calc_Networks("172.11.254.1", "172.1.254.1"))
19 Calc_Networks("172.11.254.1", "172.1.254.")
<ipython-input-154-9e53188ce6f1> in Calc_Networks(IP_One, IP_Two)
12 def Calc_Networks(IP_One , IP_Two):
13 if IP_Validation(IP_One) and IP_Validation(IP_Two):
---> 14 dis = int(IP_Two) - int(IP_One)
15 return dis
16
ValueError: invalid literal for int() with base 10: '172.1.254.1'
这些帖子 1 & 2 也帮不了我!
提前致谢
您的 Calc_Networks
代码不起作用但 calc_inclusive_subnet
起作用的原因是在 calc_inclusive_subnet
中将 ipaddress.IPv4Address
传递给了 int
,它有一个 __int__
方法,并为您提供所需的东西。但是,您的代码只是将字符串表示形式传递给 int
,它会尝试将 IP 地址解析为普通 int,而 "172.11.254.1"
不是。
如果你不想使用ipaddress
你仍然可以实现一个函数来将IP地址解析成一个整数:
def parse_ip_to_int(ip_address):
octets = ip_address.split('.')
return int.from_bytes(map(int, octets), 'big')
上面的函数将ip_address
拆分成一个字符串列表,每个字符串对应一个地址的八位字节(因此对于"172.11.254.1"
、["172", "11", "254", "1"]
)。然后我们使用 map
将这些字符串转换为 int
s。最后,我们使用有用的 int.from_bytes
,它允许我们将可迭代的八位字节转换为一个大整数。这也可以通过循环和向左移位 8 位来实现。int.from_bytes
、'big'
的第二个参数表示最重要的八位字节是第一个,这就是 IPv4 地址的编码方式。
从这里我们现在可以正确实现您的 Calc_Networks
功能。我通过使用 abs
来简化它,以确保我们获得的距离是正的,而不是像原来的 calc_inclusive_subnet
.
那样找到最小值和最大值
def Calc_Networks(IP_One, IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
return abs(parse_ip_to_int(IP_One) - parse_ip_to_int(IP_Two))
与您的初始实现类似,如果验证失败,则返回 None
。最后一点,虽然我所展示的确实产生了与你所展示的 calc_inclusive_subnet
相同的结果,但该函数所做的只是计算从起始地址到(但不包括)结束地址的地址数地址。您想要的行为可能会有所不同。
我被要求做一个应用程序来提供子网可能的主机总数,遗憾的是我不能使用 Python 提供的 ipaddress
模块所以我需要编写自己的方法来检查和验证输入的数据
我的代码是这样的:
def IP_Validation(chk_IP_vaild):
if chk_IP_vaild.count(".") == 3 and all(isIP(i) for i in chk_IP_vaild.split(".")):
return True
return False
def isIP(IP_String):
try:
return str(int(IP_String)) == IP_String and 0 <= int(IP_String) <= 255
except:
return False
def Calc_Networks(IP_One , IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
print (IP_One,IP_Two)
else:
print ("There is an error")
Calc_Networks("172.11.254.1", "172.1.254.")
Calc_Networks("172.11.254.1", "172.1.254.0")
输出
There is an error
172.11.254.1 172.1.254.0
但这只检查输入的 IP 是否为 IPv4,所以我在网上搜索和检查解决方案,我遇到了这个:
import ipaddress
def calc_inclusive_subnet(ip1, ip2): #accepts 2 IP strings
#make IP Address objects
ip1_obj=ipaddress.IPv4Address(ip1)
ip2_obj=ipaddress.IPv4Address(ip2)
if ip1_obj<=ip2_obj:
min_ip=ip1_obj
max_ip=ip2_obj
else:
min_ip=ip2_obj
max_ip=ip1_obj
distance = int(max_ip)-int(min_ip) #**
return distance
print (calc_inclusive_subnet("192.168.1.0", "192.168.2.255"))
输出
511
我注意到,如果我对使用 ipaddress
模块声明的两个 IP 进行减法运算,它会毫无问题地正确执行,因此我转到 Docs 以了解该模块如何处理IP,所以我可以使用类似的方法
使用 代码 1 进行减法会出现以下错误:
def Calc_Networks(IP_One , IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
dis = int(IP_Two) - int(IP_One)
return dis
输出为:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-154-9e53188ce6f1> in <module>
16
17
---> 18 print(Calc_Networks("172.11.254.1", "172.1.254.1"))
19 Calc_Networks("172.11.254.1", "172.1.254.")
<ipython-input-154-9e53188ce6f1> in Calc_Networks(IP_One, IP_Two)
12 def Calc_Networks(IP_One , IP_Two):
13 if IP_Validation(IP_One) and IP_Validation(IP_Two):
---> 14 dis = int(IP_Two) - int(IP_One)
15 return dis
16
ValueError: invalid literal for int() with base 10: '172.1.254.1'
这些帖子 1 & 2 也帮不了我!
提前致谢
您的 Calc_Networks
代码不起作用但 calc_inclusive_subnet
起作用的原因是在 calc_inclusive_subnet
中将 ipaddress.IPv4Address
传递给了 int
,它有一个 __int__
方法,并为您提供所需的东西。但是,您的代码只是将字符串表示形式传递给 int
,它会尝试将 IP 地址解析为普通 int,而 "172.11.254.1"
不是。
如果你不想使用ipaddress
你仍然可以实现一个函数来将IP地址解析成一个整数:
def parse_ip_to_int(ip_address):
octets = ip_address.split('.')
return int.from_bytes(map(int, octets), 'big')
上面的函数将ip_address
拆分成一个字符串列表,每个字符串对应一个地址的八位字节(因此对于"172.11.254.1"
、["172", "11", "254", "1"]
)。然后我们使用 map
将这些字符串转换为 int
s。最后,我们使用有用的 int.from_bytes
,它允许我们将可迭代的八位字节转换为一个大整数。这也可以通过循环和向左移位 8 位来实现。int.from_bytes
、'big'
的第二个参数表示最重要的八位字节是第一个,这就是 IPv4 地址的编码方式。
从这里我们现在可以正确实现您的 Calc_Networks
功能。我通过使用 abs
来简化它,以确保我们获得的距离是正的,而不是像原来的 calc_inclusive_subnet
.
def Calc_Networks(IP_One, IP_Two):
if IP_Validation(IP_One) and IP_Validation(IP_Two):
return abs(parse_ip_to_int(IP_One) - parse_ip_to_int(IP_Two))
与您的初始实现类似,如果验证失败,则返回 None
。最后一点,虽然我所展示的确实产生了与你所展示的 calc_inclusive_subnet
相同的结果,但该函数所做的只是计算从起始地址到(但不包括)结束地址的地址数地址。您想要的行为可能会有所不同。