【问题标题】:How ipaddress module in Python handles IPsPython 中的 ipaddress 模块如何处理 IP
【发布时间】:2021-03-26 19:43:20
【问题描述】:

我被要求做一个应用程序来为子网提供可能的主机总数,遗憾的是我不能使用 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,以便我可以使用类似的方法


使用 code 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'

这些帖子12 也帮不了我!

提前致谢

【问题讨论】:

    标签: python module ip


    【解决方案1】:

    您的Calc_Networks 代码不起作用但calc_inclusive_subnet 起作用的原因是在calc_inclusive_subnetipaddress.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 将这些字符串转换为ints。最后我们使用有用的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 产生了相同的结果,但该函数所做的只是计算从起始地址到但不包括结束地址的地址数。您想要的行为可能会有所不同。

    【讨论】:

      猜你喜欢
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多