如何在Python中检查IP是否在网络中?

141 投票
30 回答
220560 浏览
提问于 2025-04-15 11:23

给定一个IP地址(比如192.168.0.1),我该如何在Python中检查它是否在某个网络里(比如192.168.0.0/24)?

在Python中有没有一些通用的工具可以用来处理IP地址?比如查找主机、把IP地址转换成整数、把带有子网掩码的网络地址转换成整数等等?希望这些工具能在Python 2.5的标准库中找到。

30 个回答

175

我喜欢使用 netaddr 来实现这个功能:

from netaddr import CIDR, IP

if IP("192.168.0.1") in CIDR("192.168.0.0/24"):
    print "Yay!"

正如 arno_v 在评论中提到的,netaddr 的新版本是这样做的:

from netaddr import IPNetwork, IPAddress
if IPAddress("192.168.0.1") in IPNetwork("192.168.0.0/24"):
    print "Yay!"
203

使用ipaddress库(从3.3版本开始就已经在标准库里了,可以查看官方文档,而在PyPi上可以找到2.6/2.7版本):

>>> import ipaddress
>>> ipaddress.ip_address('192.168.0.1') in ipaddress.ip_network('192.168.0.0/24')
True

如果你想用这种方式处理很多IP地址,最好先计算一下网络掩码,比如:

n = ipaddress.ip_network('192.0.0.0/16')
netw = int(n.network_address)
mask = int(n.netmask)

然后,对于每个地址,使用以下方法计算它的二进制表示:

a = int(ipaddress.ip_address('192.0.43.10'))
a = struct.unpack('!I', socket.inet_pton(socket.AF_INET, '192.0.43.10'))[0]
a = struct.unpack('!I', socket.inet_aton('192.0.43.10'))[0]  # IPv4 only

最后,你可以简单地检查:

in_network = (a & mask) == netw
28

这篇文章告诉你可以使用socketstruct模块来实现这个功能,而且不需要太多额外的努力。我在文章中添加了一些内容,如下所示:

import socket,struct

def makeMask(n):
    "return a mask of n bits as a long integer"
    return (2L<<n-1) - 1

def dottedQuadToNum(ip):
    "convert decimal dotted quad string to long integer"
    return struct.unpack('L',socket.inet_aton(ip))[0]

def networkMask(ip,bits):
    "Convert a network address to a long integer" 
    return dottedQuadToNum(ip) & makeMask(bits)

def addressInNetwork(ip,net):
   "Is an address in a network"
   return ip & net == net

address = dottedQuadToNum("192.168.1.1")
networka = networkMask("10.0.0.0",24)
networkb = networkMask("192.168.0.0",24)
print (address,networka,networkb)
print addressInNetwork(address,networka)
print addressInNetwork(address,networkb)

这段代码的输出是:

False
True

如果你只想要一个可以处理字符串的简单函数,它看起来会像这样:

import socket,struct

def addressInNetwork(ip,net):
   "Is an address in a network"
   ipaddr = struct.unpack('L',socket.inet_aton(ip))[0]
   netaddr,bits = net.split('/')
   netmask = struct.unpack('L',socket.inet_aton(netaddr))[0] & ((2L<<int(bits)-1) - 1)
   return ipaddr & netmask == netmask

撰写回答