Python · 4 分钟阅读
IPy:IP 地址处理库
目录
处理 IP 地址、子网、掩码、广播、范围等需求时,Python 3 有 两个选择:
| 选项 | 优缺点 |
|---|---|
IPy |
老牌第三方库、API 友好;已停更多年(最后一次更新 2020) |
ipaddress |
标准库、自 Python 3 起内置;功能覆盖 95% 日常需求 |
新项目建议直接用标准库
ipaddress,0 依赖、与 Python 版本同步。
如果你接手老代码看到IPy,下面是“对照表”,快速迁移不是问题。
1. 安装(仅当用 IPy 时)
pip install IPy
Python 3.4+ 已经有
ipaddress,大部分情况下不需要再装IPy。
2. ipaddress(推荐):标准库
2.1 创建对象
import ipaddress
v4 = ipaddress.ip_address("192.168.50.20")
v6 = ipaddress.ip_address("::1")
print(v4.version) # 4
print(v6.version) # 6
自动判断是 IPv4 还是 IPv6。
2.2 网络 / 子网
net = ipaddress.ip_network("192.168.0.0/16", strict=False)
print(net.num_addresses) # 65536
print(net.network_address) # 192.168.0.0
print(net.broadcast_address) # 192.168.255.255
print(net.netmask) # 255.255.0.0
print(net.prefixlen) # 16
2.3 遍历地址
net = ipaddress.ip_network("192.168.0.0/24")
print(net.num_addresses) # 256
# /24 太小,打印前几个就行
for i, ip in enumerate(net):
if i >= 3: break
print(ip)
# 192.168.0.0
# 192.168.0.1
# 192.168.0.2
net.hosts()只给出“可用的 host 地址”,跳过网络地址与广播。
2.4 成员判断
"192.168.1.100" in ipaddress.ip_network("192.168.0.0/16") # True
ipaddress.ip_address("10.0.0.1") in ipaddress.ip_network("10.0.0.0/24") # True
2.5 整数 / 字节 / 十六进制表示
ip = ipaddress.ip_address("192.168.50.20")
print(int(ip)) # 3232255508
print(ip.packed) # b'\xc0\xa83\x14'
print(hex(int(ip))) # 0xc0a83214
print(format(int(ip), "08x"))
想看二进制:
bin(int(ip));想格式化输出可自己写format_ip。
2.6 反向解析名(PTR 记录)
ipaddress.ip_address("8.8.8.8").reverse_pointer
# '8.8.8.8.in-addr.arpa'
2.7 IPv4 与 IPv6 互转
ipaddress.IPv4Address("192.168.0.1").ipv4_mapped # ::ffff:192.168.0.1
ipaddress.IPv6Address("::ffff:c0a8:1").ipv4_mapped # ::ffff:192.168.0.1
2.8 多网络比较
a = ipaddress.ip_network("10.0.0.0/24")
b = ipaddress.ip_network("12.0.0.0/24")
print(a < b) # True
print("192.168.1.100" in ipaddress.ip_network("192.168.0.0/24")) # True
print(ipaddress.ip_network("192.168.0.0/23")
.overlaps(ipaddress.ip_network("192.168.0.0/24"))) # True
2.9 网络地址运算
n = ipaddress.ip_network("192.168.50.0/24")
print(n.network_address) # 192.168.50.0
print(n.broadcast_address) # 192.168.50.255
print(n.netmask) # 255.255.255.0
print(n.hostmask) # 0.0.0.255
print(n.with_prefixlen) # 192.168.50.0/24
print(n.with_netmask) # 192.168.50.0/255.255.255.0
2.10 拆分子网
supernet = ipaddress.ip_network("192.168.0.0/16")
for sub in supernet.subnets(new_prefix=18):
print(sub)
# 192.168.0.0/18
# 192.168.64.0/18
# 192.168.128.0/18
# 192.168.192.0/18
3. IPy(已停更):老 API 对照
如果你接手老代码,可以按下面方式改写:
IPy 用法 |
ipaddress 等价 |
|---|---|
IP("192.168.50.0/24").version() |
ipaddress.ip_address(...).version |
IP("192.168.0.0/16").len() |
ipaddress.ip_network(...).num_addresses |
IP("...").net() |
.network_address |
IP("...").netmask() |
.netmask |
IP("...").broadcast() |
.broadcast_address |
IP("...").reverseName() |
.reverse_pointer |
IP("...").int() |
int(...) |
IP("...").strHex() |
format(int(...), '08x') |
IP("...").iptype() |
自己判断(is_global / is_private 等) |
IP("192.168.0.0/24") in IP(...) |
ipaddress.ip_address(...) in ipaddress.ip_network(...) |
IP(...).overlaps(...) |
ipaddress.ip_network(...).overlaps(...) |
IPy 的 iptype() 区分 “LOOPBACK / PRIVATE / PUBLIC / …”,ipaddress 改为
is_loopback / is_private / is_global / is_multicast / is_reserved 等
几个 bool 方法:
ip = ipaddress.ip_address("10.0.0.1")
print(ip.is_private) # True
print(ip.is_global) # False
print(ip.is_loopback) # False
4. 综合案例:IP 段信息查询
import ipaddress
def describe(s: str) -> str:
"""打印 IP / 网段 的网络信息。"""
if "/" in s:
net = ipaddress.ip_network(s, strict=False)
return (
f"network : {net}\n"
f"mask : {net.netmask}\n"
f"broadcast : {net.broadcast_address}\n"
f"num_hosts : {net.num_addresses}\n"
f"first host: {next(net.hosts()) if net.num_addresses > 2 else net.network_address}\n"
f"last host : {net.broadcast_address - 1 if net.num_addresses > 2 else net.broadcast_address}"
)
else:
ip = ipaddress.ip_address(s)
return (
f"ip : {ip}\n"
f"version : IPv{ip.version}\n"
f"private : {ip.is_private}\n"
f"global : {ip.is_global}\n"
f"reverse : {ip.reverse_pointer}"
)
if __name__ == "__main__":
print(describe("192.168.50.0/24"))
print()
print(describe("8.8.8.8"))
5. 选型
| 需求 | 用什么 |
|---|---|
| 解析 IP、判定私有/公网、遍历网段 | ipaddress(标准库) |
想用更“人性化”的 API、需要 iptype |
IPy(不推荐新项目) |
| IP 反查域名(PTR) | ipaddress.ip_address(...).reverse_pointer 或 socket.gethostbyaddr |
| IPv6 转换 / 6to4 / 4to6 | ipaddress 已覆盖常见场景 |
| 复杂的 IP 归属地查询 | 借助 ip-api.com / MaxMind / ip2region 等数据库 |
6. 小结
- 新项目用
ipaddress:标准库、0 依赖、文档全。 IPy还能用,但已停更多年,复杂 IPv6 场景偶尔会有 bug。- 需要 IP 归属地信息时,
ipaddress不会替你做;要自己接 GeoIP 库。