从IP地址获取子网

9

我正在尝试获取给定IP地址的子网掩码。

例如:

1

子网掩码:255.255.255.0

输入:192.178.2.55

输出:192.178.2.0

2

子网掩码:255.255.0.0

输入:192.178.2.55

输出:192.178.0.0

目前,我使用以下方法(对于子网掩码255.255.255.0)进行操作:

ip =  '192.178.2.55'
subnet = '.'.join(ip.split('.')[:2]) + '.0.0'
subnet
'192.178.0.0'

我看到Python有一个ipaddress库。然而,我找不到可以完成上述任务的方法。
奖励:由于ipaddress支持IPv4和IPv6,如果同一个函数可以用于两者,那就更好了。
2个回答

18
ipaddress.ip_network 函数可以接受任何 IPv4NetworkIPv6Network 可以接受的字符串格式,包括 address/mask 格式。

由于您实际上并没有传递网络地址,而是设置了主机位的网络中的地址,因此您需要使用 strict=False

因此:

>>> net = ipaddress.ip_network('192.178.2.55/255.255.255.0', strict=False)
>>> net
IPv4Network('192.178.2.0/24')
>>> net.network_address
IPv4Address('192.178.2.0')
>>> net.netmask
IPv4Address('255.255.255.0')

或者,您可以使用ip_interface,并从那里提取网络:


>>> iface = ipaddress.ip_interface('192.178.2.55/255.255.255.0')
>>> iface
IPv4Interface('192.178.2.55/24')
>>> iface.network
IPv4Network('192.178.2.0/24')
>>> iface.netmask
IPv4Address('255.255.255.0')
>>> iface.ip
IPv4Address('192.178.2.55')
>>> iface.network.network_address
IPv4Address('192.178.2.0')

你需要选择哪一个取决于你要表示的具体内容。请注意,接口类型是地址类型的子类,当然它们会记住用于构建它们的原始地址,而网络类则记住网络地址; 这两者通常是决定因素之一。

当然,这两种类型都可以很好地与IPv6配合使用:

>>> ipaddress.ip_interface('2001:db8::1000/32')
IPv6Interface('2001:db8::1000/32')
>>> ipaddress.ip_interface('2001:db8::1000/32').network.network_address
IPv6Address('2001:db8::')

非常适合我的使用情况。谢谢。 - Spandan Brahmbhatt

5

子网掩码是一个二进制掩码,必须与IP地址进行按位and运算。您可以自己应用掩码:

".".join(map(str, [i & m # Apply the mask
          for i,m in zip(map(int, ip.split(".")),
                         map(int, subnet.split(".")))]))
#'192.178.2.0'

这个解决方案仅适用于IPv4地址。


使用列表推导式替代map函数:'.'.join([str(z) for z in [x&y for x, y in zip([int(x) for x in ip.split('.')], [int(y) for y in subnet.split('.')])]]) - Leon Chang
@LeonChang 为什么?map更易于理解且更符合惯用语。 - DYZ
同意,这样做更快且代码量更少。以下是一个纯映射版本:'.'.join(map(str, map(lambda x, y: x&y, map(int, ip.split(".")), map(int, subnet.split("."))))) - Leon Chang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接