当前位置:首页 > 文章列表 > 文章 > python教程 > Python ipaddress.collapse_addresses 怎样合并连续网段

Python ipaddress.collapse_addresses 怎样合并连续网段

来源:17golang原创 2026-11-01 10:04:44 0浏览 收藏

如果一组网段来自配置文件、访问控制列表或地址池,直接把它们原样输出,往往会留下重复项和可以继续合并的相邻块。Python 标准库的 ipaddress.collapse_addresses() 可以把同一 IP 版本的网络对象交给 CIDR 规则统一折叠,返回更紧凑的网段迭代器。

最小用法是先用 ip_network() 把输入转换为网络对象,再调用 collapse_addresses()。IPv4 和 IPv6 要分批处理;函数只会合并满足前缀对齐条件的网络,不会因为两个网段“看起来相邻”就强行扩大范围。

官方文档:https://docs.python.org/3/library/ipaddress.html#ipaddress.collapse_addresses

先分清它合并的是什么

collapse_addresses() 处理的是 IPv4Network 或 IPv6Network 对象组成的可迭代对象,不是任意字符串列表。它返回一个迭代器,里面仍然是网络对象。

“连续网段”也有一个容易忽略的限制:两个网络不仅要覆盖连续的地址范围,还要能组成一个合法的更大 CIDR 网络。例如 192.0.2.0/25 和 192.0.2.128/25 正好组成 192.0.2.0/24;如果边界没有按更大前缀对齐,函数就会保留为多个结果。

同版本网络对象经过规范化后进入连续网段合并流程的结构示意图
图1:从网络对象、IP 版本分组到合并入口的静态结构示意图,不是运行截图。

最小写法:输入转换后直接折叠

下面的例子把字符串解析成网络对象,再把返回迭代器转换为列表。注释只标出输入类型、惰性返回值和最终展示这几个关键点。

from ipaddress import collapse_addresses, ip_network


def collapse_cidrs(values: list[str]) -> list[str]:
    # 先把文本统一解析为网络对象,strict=False 会屏蔽误写的主机位
    networks = [ip_network(value, strict=False) for value in values]
    # 函数返回迭代器;物化后更适合交给接口或配置渲染层
    collapsed = collapse_addresses(networks)
    # 用 str() 输出规范化后的 CIDR 文本
    return [str(network) for network in collapsed]


values = [
    "192.0.2.128/25",
    "192.0.2.0/25",
    "192.0.2.0/25",  # 重复输入不会让结果重复扩大
]
print(collapse_cidrs(values))
['192.0.2.0/24']

输入顺序不影响这个示例的折叠结果,重复的 /25 也不会把地址范围扩展到 192.0.3.0/24。如果业务还需要保留原始输入顺序,应在合并前另行保存原始列表。

为什么有些相邻网段仍然不能合并

合并的目标必须是一个合法的更大网络。下面的函数把几个边界样例放在一起,便于观察“可合并”“仅相邻”和“重复覆盖”的区别。

from ipaddress import collapse_addresses, ip_network


def show_case(label: str, values: list[str]) -> None:
    # strict=False 只负责把带主机位的输入归一化,不改变合并规则
    networks = [ip_network(value, strict=False) for value in values]
    result = [str(network) for network in collapse_addresses(networks)]
    print(f"{label}: {result}")


show_case("两个对齐的 /25", ["192.0.2.0/25", "192.0.2.128/25"])
show_case("两个未形成更大块的 /26", ["192.0.2.0/26", "192.0.2.128/26"])
show_case("大网覆盖小网", ["198.51.100.0/24", "198.51.100.0/25"])
两个对齐的 /25: ['192.0.2.0/24']
两个未形成更大块的 /26: ['192.0.2.0/26', '192.0.2.128/26']
大网覆盖小网: ['198.51.100.0/24']

第二组虽然都在同一个 /24 范围内,但中间还有一段没有覆盖,不能直接变成更大的连续块。判断时不要只比较一个网段的结束地址和另一个网段的起始地址,还要检查它们是否能按同一层级的 CIDR 边界配对。

IPv4 和 IPv6 要分开折叠

官方接口明确要求输入中的网络对象不能混合 IP 版本。实际项目常把两种地址都读进同一个列表,因此最好在调用前按 version 分组,或者在发现混合输入时给出业务层错误。

from collections.abc import Iterable
from ipaddress import IPv4Network, IPv6Network, collapse_addresses, ip_network


def collapse_by_version(values: Iterable[str]) -> dict[int, list[str]]:
    # 解析阶段统一得到网络对象,同时保留 Python 的版本属性
    networks = [ip_network(value, strict=False) for value in values]
    groups: dict[int, list[IPv4Network | IPv6Network]] = {4: [], 6: []}
    for network in networks:
        # 用 version 分组,避免把 IPv4 和 IPv6 一起传给 collapse_addresses
        groups[network.version].append(network)

    result: dict[int, list[str]] = {}
    for version, group in groups.items():
        if group:
            # 每组单独折叠,并把迭代器转换成稳定的文本结果
            result[version] = [str(network) for network in collapse_addresses(group)]
    return result


print(collapse_by_version([
    "192.0.2.0/25",
    "192.0.2.128/25",
    "2001:db8::/65",
    "2001:db8:0:0:8000::/65",
]))
{4: ['192.0.2.0/24'], 6: ['2001:db8::/64']}

如果不想分组,也可以在进入函数前直接拒绝同时出现版本 4 和版本 6 的输入。这样错误会更早、更容易定位,避免网络策略层悄悄丢掉其中一类地址。

输出接入配置前要固定边界

collapse_addresses() 返回的是迭代器,所以调用一次后就会被消费。要把结果交给多个下游步骤,先转换成列表;要对文本排序,也应排序网络对象或统一的字符串结果,而不是在多个地方重复遍历原迭代器。

from ipaddress import collapse_addresses, ip_network


def compact_for_config(values: list[str]) -> list[str]:
    # 解析并折叠后立刻物化,后续渲染、统计都复用同一份结果
    collapsed = list(collapse_addresses(ip_network(value, strict=False) for value in values))
    # 网络对象支持按网络地址和前缀进行排序,输出顺序更适合配置 diff
    collapsed.sort()
    return [network.with_prefixlen for network in collapsed]


print(compact_for_config([
    "203.0.113.128/25",
    "203.0.113.0/25",
    "198.51.100.0/24",
]))
['198.51.100.0/24', '203.0.113.0/24']

排序只是输出层的确定性处理,不会改变折叠规则。若下游把网段作为集合比较,建议把 with_prefixlen 结果作为规范化字符串保存,便于日志、缓存键或配置差异对比。

连续网段合并后形成更大 CIDR 网络以及保留未对齐网段的结果边界示意图
图2:可合并的对齐块与必须保留原样的边界结果示意图,不是运行截图。

值班排查时可以按这张清单处理

  1. 先确认列表元素是网络对象,而不是未解析的字符串或接口对象。
  2. 读取 network.version,混合 IPv4/IPv6 时按版本分组或提前拒绝。
  3. 对带主机位的输入决定是否使用 strict=False;这一步属于输入归一化,不是合并本身。
  4. 把返回迭代器物化一次,记录折叠前后的数量和最终 CIDR 文本。
  5. 用一对明确对齐的网络做回归样例,再用一个未对齐的相邻样例确认没有过度扩大范围。

常见问题

collapse_addresses() 能直接接受字符串吗?

不要这样用。先通过 ip_network() 把字符串解析为网络对象,再传入折叠函数。

IPv4 和 IPv6 可以放在同一个列表里吗?

不可以混合调用。先按 version 分组,分别折叠,或者在业务层拒绝混合输入。

两个网段地址连续就一定会合并吗?

不一定。它们还必须能组成符合边界对齐要求的更大 CIDR 网络;否则结果会保留多个网段。

为什么我第二次遍历结果为空?

返回值是迭代器,第一次遍历后已经消费。把它转成列表后再交给多个处理步骤。

归纳起来,collapse_addresses() 最适合做“同版本网络对象的 CIDR 归并”:先规范化输入,再分版本折叠,最后物化并固定输出。它负责地址范围的紧凑表达,不负责替你决定路由策略、访问权限或设备配置。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Python logging.basicConfig(force=True) 怎样重置根日志配置Python logging.basicConfig(force=True) 怎样重置根日志配置
上一篇
Python logging.basicConfig(force=True) 怎样重置根日志配置
Linux fanotify 怎样读取 FID 事件定位文件对象
下一篇
Linux fanotify 怎样读取 FID 事件定位文件对象
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    821次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    816次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    905次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    876次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    698次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码