“Python/docs/3.9/howto/ipaddress”的版本间差异
(autoload) |
小 (Page commit) |
||
第1行: | 第1行: | ||
+ | {{DISPLAYTITLE:ipaddress 模块简介 — Python 文档}} | ||
<div id="an-introduction-to-the-ipaddress-module" class="section"> | <div id="an-introduction-to-the-ipaddress-module" class="section"> | ||
<span id="ipaddress-howto"></span> | <span id="ipaddress-howto"></span> | ||
− | = | + | = ipaddress 模块介绍 = |
− | ; | + | ; 作者 |
− | : | + | : 彼得·穆迪 |
− | ; | + | ; 作者 |
− | : | + | : 尼克·科格兰 |
<div class="topic"> | <div class="topic"> | ||
− | + | 概述 | |
− | + | 本文档旨在简要介绍 [[../../library/ipaddress#module-ipaddress|ipaddress]] 模块。 它主要针对不熟悉 IP 网络术语的用户,但对于想要了解 [[../../library/ipaddress#module-ipaddress|ipaddress]] 如何表示 IP 网络寻址概念的网络工程师也可能有用。 | |
− | [[../../library/ipaddress#module-ipaddress| | ||
− | |||
− | |||
− | |||
第23行: | 第20行: | ||
<div id="creating-address-network-interface-objects" class="section"> | <div id="creating-address-network-interface-objects" class="section"> | ||
− | == | + | == 创建地址/网络/接口对象 == |
− | + | 由于 [[../../library/ipaddress#module-ipaddress|ipaddress]] 是一个用于检查和操作 IP 地址的模块,因此您要做的第一件事就是创建一些对象。 您可以使用 [[../../library/ipaddress#module-ipaddress|ipaddress]] 从字符串和整数创建对象。 | |
− | |||
− | [[../../library/ipaddress#module-ipaddress| | ||
<div id="a-note-on-ip-versions" class="section"> | <div id="a-note-on-ip-versions" class="section"> | ||
− | === | + | === 关于 IP 版本的说明 === |
− | + | 对于不是特别熟悉 IP 寻址的读者,重要的是要知道 Internet 协议目前正在从协议的第 4 版迁移到第 6 版。 这种转变的发生主要是因为该协议的第 4 版没有提供足够的地址来满足全世界的需求,特别是考虑到直接连接到互联网的设备数量不断增加。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 详细解释两个版本的协议差异超出了本介绍的范围,但读者至少需要意识到这两个版本的存在,并且有时需要强制使用一个版本或其他。 | |
− | |||
− | |||
− | |||
第49行: | 第36行: | ||
<div id="ip-host-addresses" class="section"> | <div id="ip-host-addresses" class="section"> | ||
− | === IP | + | === IP 主机地址 === |
− | + | 地址,通常称为“主机地址”,是使用 IP 寻址时最基本的单位。 创建地址最简单的方法是使用 [[../../library/ipaddress#ipaddress|ipaddress.ip_address()]] 工厂函数,它会根据传入的值自动确定是创建 IPv4 还是 IPv6 地址: | |
− | |||
− | |||
− | |||
− | |||
<div class="doctest highlight-default notranslate"> | <div class="doctest highlight-default notranslate"> | ||
第61行: | 第44行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> ipaddress.ip_address('192.0.2.1') |
IPv4Address('192.0.2.1') | IPv4Address('192.0.2.1') | ||
− | + | >>> ipaddress.ip_address('2001:DB8::1') | |
− | IPv6Address('2001:db8::1')</ | + | IPv6Address('2001:db8::1')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 地址也可以直接从整数创建。 将适合 32 位的值假定为 IPv4 地址: | |
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第76行: | 第58行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_address(3221225985) |
IPv4Address('192.0.2.1') | IPv4Address('192.0.2.1') | ||
− | + | >>> ipaddress.ip_address(42540766411282592856903984951653826561) | |
− | IPv6Address('2001:db8::1')</ | + | IPv6Address('2001:db8::1')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 要强制使用 IPv4 或 IPv6 地址,可以直接调用相关类。 这对于强制为小整数创建 IPv6 地址特别有用: | |
− | |||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第92行: | 第72行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_address(1) |
IPv4Address('0.0.0.1') | IPv4Address('0.0.0.1') | ||
− | + | >>> ipaddress.IPv4Address(1) | |
IPv4Address('0.0.0.1') | IPv4Address('0.0.0.1') | ||
− | + | >>> ipaddress.IPv6Address(1) | |
− | IPv6Address('::1')</ | + | IPv6Address('::1')</syntaxhighlight> |
</div> | </div> | ||
第106行: | 第86行: | ||
<div id="defining-networks" class="section"> | <div id="defining-networks" class="section"> | ||
− | === | + | === 定义网络 === |
− | + | 主机地址通常组合到 IP 网络中,因此 [[../../library/ipaddress#module-ipaddress|ipaddress]] 提供了一种创建、检查和操作网络定义的方法。 IP 网络对象由定义作为该网络一部分的主机地址范围的字符串构成。 该信息的最简单形式是“网络地址/网络前缀”对,其中前缀定义了前导位的数量,用于确定地址是否是网络的一部分,网络地址定义了预期值那些位。 | |
− | [[../../library/ipaddress#module-ipaddress| | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 至于地址,提供了一个工厂函数,可以自动确定正确的 IP 版本: | |
− | IP | ||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第124行: | 第96行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_network('192.0.2.0/24') |
IPv4Network('192.0.2.0/24') | IPv4Network('192.0.2.0/24') | ||
− | + | >>> ipaddress.ip_network('2001:db8::0/96') | |
− | IPv6Network('2001:db8::/96')</ | + | IPv6Network('2001:db8::/96')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 网络对象不能设置任何主机位。 这样做的实际效果是 <code>192.0.2.1/24</code> 没有描述网络。 此类定义被称为接口对象,因为 ip-on-a-network 表示法通常用于描述给定网络上计算机的网络接口,并在下一节中进一步描述。 | |
− | |||
− | |||
− | |||
− | |||
− | + | 默认情况下,尝试创建设置了主机位的网络对象将导致引发 [[../../library/exceptions#ValueError|ValueError]]。 要请求将附加位强制为零,可以将标志 <code>strict=False</code> 传递给构造函数: | |
− | |||
− | |||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第147行: | 第112行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_network('192.0.2.1/24') |
Traceback (most recent call last): | Traceback (most recent call last): | ||
... | ... | ||
ValueError: 192.0.2.1/24 has host bits set | ValueError: 192.0.2.1/24 has host bits set | ||
− | + | >>> ipaddress.ip_network('192.0.2.1/24', strict=False) | |
− | IPv4Network('192.0.2.0/24')</ | + | IPv4Network('192.0.2.0/24')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 虽然字符串形式提供了更大的灵活性,但网络也可以用整数定义,就像主机地址一样。 在这种情况下,网络被认为只包含由整数标识的单个地址,因此网络前缀包括整个网络地址: | |
− | |||
− | |||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第166行: | 第128行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_network(3221225984) |
IPv4Network('192.0.2.0/32') | IPv4Network('192.0.2.0/32') | ||
− | + | >>> ipaddress.ip_network(42540766411282592856903984951653826560) | |
− | IPv6Network('2001:db8::/128')</ | + | IPv6Network('2001:db8::/128')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 与地址一样,可以通过直接调用类构造函数而不是使用工厂函数来强制创建特定类型的网络。 | |
− | |||
− | |||
第182行: | 第142行: | ||
<div id="host-interfaces" class="section"> | <div id="host-interfaces" class="section"> | ||
− | === | + | === 主机接口 === |
− | + | 如上所述,如果您需要描述特定网络上的地址,地址和网络类别都不够。 像 <code>192.0.2.1/24</code> 这样的符号通常被网络工程师和为防火墙和路由器编写工具的人用作“网络 <code>192.0.2.0/24</code> 上的主机 <code>192.0.2.1</code>”的简写,因此,[ X196X]ipaddress 提供了一组将地址与特定网络相关联的混合类。 用于创建的接口与用于定义网络对象的接口相同,只是地址部分不限于网络地址。 | |
− | |||
− | |||
− | |||
− | <code>192.0.2. | ||
− | |||
− | |||
− | |||
− | |||
<div class="doctest highlight-default notranslate"> | <div class="doctest highlight-default notranslate"> | ||
第198行: | 第150行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> ipaddress.ip_interface('192.0.2.1/24') |
IPv4Interface('192.0.2.1/24') | IPv4Interface('192.0.2.1/24') | ||
− | + | >>> ipaddress.ip_interface('2001:db8::1/96') | |
− | IPv6Interface('2001:db8::1/96')</ | + | IPv6Interface('2001:db8::1/96')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 接受整数输入(与网络一样),并且可以通过直接调用相关构造函数来强制使用特定 IP 版本。 | |
− | |||
第215行: | 第166行: | ||
<div id="inspecting-address-network-interface-objects" class="section"> | <div id="inspecting-address-network-interface-objects" class="section"> | ||
− | == | + | == 检查地址/网络/接口对象 == |
− | + | 您在创建 IPv(4|6)(Address|Network|Interface) 对象时遇到了麻烦,因此您可能想要获取有关它的信息。 [[../../library/ipaddress#module-ipaddress|ipaddress]] 试图让这件事变得简单而直观。 | |
− | |||
− | |||
− | + | 提取IP版本: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第227行: | 第176行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> addr4 = ipaddress.ip_address('192.0.2.1') |
− | + | >>> addr6 = ipaddress.ip_address('2001:db8::1') | |
− | + | >>> addr6.version | |
6 | 6 | ||
− | + | >>> addr4.version | |
− | 4</ | + | 4</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 从接口获取网络: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第243行: | 第192行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> host4 = ipaddress.ip_interface('192.0.2.1/24') |
− | + | >>> host4.network | |
IPv4Network('192.0.2.0/24') | IPv4Network('192.0.2.0/24') | ||
− | + | >>> host6 = ipaddress.ip_interface('2001:db8::1/96') | |
− | + | >>> host6.network | |
− | IPv6Network('2001:db8::/96')</ | + | IPv6Network('2001:db8::/96')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 找出网络中有多少个单独的地址: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第259行: | 第208行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> net4 = ipaddress.ip_network('192.0.2.0/24') |
− | + | >>> net4.num_addresses | |
256 | 256 | ||
− | + | >>> net6 = ipaddress.ip_network('2001:db8::0/96') | |
− | + | >>> net6.num_addresses | |
− | 4294967296</ | + | 4294967296</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 遍历网络上的“可用”地址: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第275行: | 第224行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> net4 = ipaddress.ip_network('192.0.2.0/24') |
− | + | >>> for x in net4.hosts(): | |
... print(x) | ... print(x) | ||
192.0.2.1 | 192.0.2.1 | ||
第285行: | 第234行: | ||
192.0.2.252 | 192.0.2.252 | ||
192.0.2.253 | 192.0.2.253 | ||
− | 192.0.2.254</ | + | 192.0.2.254</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 获取网络掩码(即 设置对应于网络前缀的位)或主机掩码(不属于网络掩码的任何位): | |
− | |||
<div class="doctest highlight-default notranslate"> | <div class="doctest highlight-default notranslate"> | ||
第297行: | 第245行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python">>>> net4 = ipaddress.ip_network('192.0.2.0/24') |
− | + | >>> net4.netmask | |
IPv4Address('255.255.255.0') | IPv4Address('255.255.255.0') | ||
− | + | >>> net4.hostmask | |
IPv4Address('0.0.0.255') | IPv4Address('0.0.0.255') | ||
− | + | >>> net6 = ipaddress.ip_network('2001:db8::0/96') | |
− | + | >>> net6.netmask | |
IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::') | IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::') | ||
− | + | >>> net6.hostmask | |
− | IPv6Address('::ffff:ffff')</ | + | IPv6Address('::ffff:ffff')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 分解或压缩地址: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第317行: | 第265行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> addr6.exploded |
'2001:0db8:0000:0000:0000:0000:0000:0001' | '2001:0db8:0000:0000:0000:0000:0000:0001' | ||
− | + | >>> addr6.compressed | |
'2001:db8::1' | '2001:db8::1' | ||
− | + | >>> net6.exploded | |
'2001:0db8:0000:0000:0000:0000:0000:0000/96' | '2001:0db8:0000:0000:0000:0000:0000:0000/96' | ||
− | + | >>> net6.compressed | |
− | '2001:db8::/96'</ | + | '2001:db8::/96'</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 虽然 IPv4 不支持扩展或压缩,但关联对象仍提供相关属性,以便版本中立代码可以轻松确保对 IPv6 地址使用最简洁或最详细的形式,同时仍能正确处理 IPv4 地址。 | |
− | |||
− | |||
− | |||
第338行: | 第283行: | ||
<div id="networks-as-lists-of-addresses" class="section"> | <div id="networks-as-lists-of-addresses" class="section"> | ||
− | == | + | == 作为地址列表的网络 == |
− | + | 将网络视为列表有时很有用。 这意味着可以像这样对它们进行索引: | |
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第347行: | 第291行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> net4[1] |
IPv4Address('192.0.2.1') | IPv4Address('192.0.2.1') | ||
− | + | >>> net4[-1] | |
IPv4Address('192.0.2.255') | IPv4Address('192.0.2.255') | ||
− | + | >>> net6[1] | |
IPv6Address('2001:db8::1') | IPv6Address('2001:db8::1') | ||
− | + | >>> net6[-1] | |
− | IPv6Address('2001:db8::ffff:ffff')</ | + | IPv6Address('2001:db8::ffff:ffff')</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 这也意味着网络对象适合使用这样的列表成员测试语法: | |
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第366行: | 第309行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">if address in network: |
− | # do something</ | + | # do something</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 基于网络前缀有效地完成遏制测试: | |
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第378行: | 第321行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> addr4 = ipaddress.ip_address('192.0.2.1') |
− | + | >>> addr4 in ipaddress.ip_network('192.0.2.0/24') | |
True | True | ||
− | + | >>> addr4 in ipaddress.ip_network('192.0.3.0/24') | |
− | False</ | + | False</syntaxhighlight> |
</div> | </div> | ||
第391行: | 第334行: | ||
<div id="comparisons" class="section"> | <div id="comparisons" class="section"> | ||
− | == | + | == 比较 == |
− | [[../../library/ipaddress#module-ipaddress| | + | [[../../library/ipaddress#module-ipaddress|ipaddress]] 提供了一些简单的、希望直观的方法来比较对象,在那里它是有意义的: |
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第400行: | 第342行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_address('192.0.2.1') < ipaddress.ip_address('192.0.2.2') |
− | True</ | + | True</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 如果您尝试比较不同版本或不同类型的对象,则会引发 [[../../library/exceptions#TypeError|TypeError]] 异常。 | |
− | |||
第413行: | 第354行: | ||
<div id="using-ip-addresses-with-other-modules" class="section"> | <div id="using-ip-addresses-with-other-modules" class="section"> | ||
− | == | + | == 将 IP 地址与其他模块一起使用 == |
− | + | 其他使用 IP 地址的模块(例如 [[../../library/socket#module-socket|socket]])通常不会直接接受来自该模块的对象。 相反,它们必须被强制转换为其他模块将接受的整数或字符串: | |
− | |||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第423行: | 第362行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> addr4 = ipaddress.ip_address('192.0.2.1') |
− | + | >>> str(addr4) | |
'192.0.2.1' | '192.0.2.1' | ||
− | + | >>> int(addr4) | |
− | 3221225985</ | + | 3221225985</syntaxhighlight> |
</div> | </div> | ||
第436行: | 第375行: | ||
<div id="getting-more-detail-when-instance-creation-fails" class="section"> | <div id="getting-more-detail-when-instance-creation-fails" class="section"> | ||
− | == | + | == 实例创建失败时获取更多详细信息 == |
− | + | 使用与版本无关的工厂函数创建地址/网络/接口对象时,任何错误都将报告为 [[../../library/exceptions#ValueError|ValueError]] 并带有一般错误消息,仅说明传入的值未被识别为该类型的对象. 缺少特定错误是因为有必要知道值是 ''supposed'' 是 IPv4 还是 IPv6,以便提供有关拒绝的原因的更多详细信息。 | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | 为了支持访问此附加细节有用的用例,各个类构造函数实际上引发了 [[../../library/exceptions#ValueError|ValueError]] 子类 [[../../library/ipaddress#ipaddress|ipaddress.AddressValueError]] 和 [[../../library/ipaddress#ipaddress|ipaddress.NetmaskValueError]]准确指出定义的哪一部分未能正确解析。 | |
− | |||
− | [[../../library/exceptions#ValueError| | ||
− | [[../../library/ipaddress#ipaddress| | ||
− | |||
− | + | 直接使用类构造函数时,错误消息要详细得多。 例如: | |
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第458行: | 第387行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">>>> ipaddress.ip_address("192.168.0.256") |
Traceback (most recent call last): | Traceback (most recent call last): | ||
... | ... | ||
ValueError: '192.168.0.256' does not appear to be an IPv4 or IPv6 address | ValueError: '192.168.0.256' does not appear to be an IPv4 or IPv6 address | ||
− | + | >>> ipaddress.IPv4Address("192.168.0.256") | |
Traceback (most recent call last): | Traceback (most recent call last): | ||
... | ... | ||
− | ipaddress.AddressValueError: Octet 256 ( | + | ipaddress.AddressValueError: Octet 256 (> 255) not permitted in '192.168.0.256' |
− | + | >>> ipaddress.ip_network("192.168.0.1/64") | |
Traceback (most recent call last): | Traceback (most recent call last): | ||
... | ... | ||
ValueError: '192.168.0.1/64' does not appear to be an IPv4 or IPv6 network | ValueError: '192.168.0.1/64' does not appear to be an IPv4 or IPv6 network | ||
− | + | >>> ipaddress.IPv4Network("192.168.0.1/64") | |
Traceback (most recent call last): | Traceback (most recent call last): | ||
... | ... | ||
− | ipaddress.NetmaskValueError: '64' is not a valid netmask</ | + | ipaddress.NetmaskValueError: '64' is not a valid netmask</syntaxhighlight> |
</div> | </div> | ||
</div> | </div> | ||
− | + | 但是,这两个特定于模块的异常都将 [[../../library/exceptions#ValueError|ValueError]] 作为它们的父类,因此如果您不关心特定类型的错误,您仍然可以编写如下代码: | |
− | |||
− | |||
<div class="highlight-python3 notranslate"> | <div class="highlight-python3 notranslate"> | ||
第487行: | 第414行: | ||
<div class="highlight"> | <div class="highlight"> | ||
− | < | + | <syntaxhighlight lang="python3">try: |
network = ipaddress.IPv4Network(address) | network = ipaddress.IPv4Network(address) | ||
except ValueError: | except ValueError: | ||
− | print('address/netmask is invalid for IPv4:', address)</ | + | print('address/netmask is invalid for IPv4:', address)</syntaxhighlight> |
</div> | </div> | ||
第499行: | 第426行: | ||
</div> | </div> | ||
+ | <div class="clearer"> | ||
− | [[Category:Python 3.9 | + | |
+ | |||
+ | </div> | ||
+ | |||
+ | [[Category:Python 3.9 文档]] |
2021年10月31日 (日) 04:50的最新版本
ipaddress 模块介绍
- 作者
- 彼得·穆迪
- 作者
- 尼克·科格兰
创建地址/网络/接口对象
由于 ipaddress 是一个用于检查和操作 IP 地址的模块,因此您要做的第一件事就是创建一些对象。 您可以使用 ipaddress 从字符串和整数创建对象。
关于 IP 版本的说明
对于不是特别熟悉 IP 寻址的读者,重要的是要知道 Internet 协议目前正在从协议的第 4 版迁移到第 6 版。 这种转变的发生主要是因为该协议的第 4 版没有提供足够的地址来满足全世界的需求,特别是考虑到直接连接到互联网的设备数量不断增加。
详细解释两个版本的协议差异超出了本介绍的范围,但读者至少需要意识到这两个版本的存在,并且有时需要强制使用一个版本或其他。
IP 主机地址
地址,通常称为“主机地址”,是使用 IP 寻址时最基本的单位。 创建地址最简单的方法是使用 ipaddress.ip_address() 工厂函数,它会根据传入的值自动确定是创建 IPv4 还是 IPv6 地址:
地址也可以直接从整数创建。 将适合 32 位的值假定为 IPv4 地址:
要强制使用 IPv4 或 IPv6 地址,可以直接调用相关类。 这对于强制为小整数创建 IPv6 地址特别有用:
定义网络
主机地址通常组合到 IP 网络中,因此 ipaddress 提供了一种创建、检查和操作网络定义的方法。 IP 网络对象由定义作为该网络一部分的主机地址范围的字符串构成。 该信息的最简单形式是“网络地址/网络前缀”对,其中前缀定义了前导位的数量,用于确定地址是否是网络的一部分,网络地址定义了预期值那些位。
至于地址,提供了一个工厂函数,可以自动确定正确的 IP 版本:
网络对象不能设置任何主机位。 这样做的实际效果是 192.0.2.1/24
没有描述网络。 此类定义被称为接口对象,因为 ip-on-a-network 表示法通常用于描述给定网络上计算机的网络接口,并在下一节中进一步描述。
默认情况下,尝试创建设置了主机位的网络对象将导致引发 ValueError。 要请求将附加位强制为零,可以将标志 strict=False
传递给构造函数:
虽然字符串形式提供了更大的灵活性,但网络也可以用整数定义,就像主机地址一样。 在这种情况下,网络被认为只包含由整数标识的单个地址,因此网络前缀包括整个网络地址:
与地址一样,可以通过直接调用类构造函数而不是使用工厂函数来强制创建特定类型的网络。
主机接口
如上所述,如果您需要描述特定网络上的地址,地址和网络类别都不够。 像 192.0.2.1/24
这样的符号通常被网络工程师和为防火墙和路由器编写工具的人用作“网络 192.0.2.0/24
上的主机 192.0.2.1
”的简写,因此,[ X196X]ipaddress 提供了一组将地址与特定网络相关联的混合类。 用于创建的接口与用于定义网络对象的接口相同,只是地址部分不限于网络地址。
接受整数输入(与网络一样),并且可以通过直接调用相关构造函数来强制使用特定 IP 版本。
检查地址/网络/接口对象
您在创建 IPv(4|6)(Address|Network|Interface) 对象时遇到了麻烦,因此您可能想要获取有关它的信息。 ipaddress 试图让这件事变得简单而直观。
提取IP版本:
从接口获取网络:
找出网络中有多少个单独的地址:
遍历网络上的“可用”地址:
获取网络掩码(即 设置对应于网络前缀的位)或主机掩码(不属于网络掩码的任何位):
分解或压缩地址:
虽然 IPv4 不支持扩展或压缩,但关联对象仍提供相关属性,以便版本中立代码可以轻松确保对 IPv6 地址使用最简洁或最详细的形式,同时仍能正确处理 IPv4 地址。
作为地址列表的网络
将网络视为列表有时很有用。 这意味着可以像这样对它们进行索引:
这也意味着网络对象适合使用这样的列表成员测试语法:
基于网络前缀有效地完成遏制测试:
实例创建失败时获取更多详细信息
使用与版本无关的工厂函数创建地址/网络/接口对象时,任何错误都将报告为 ValueError 并带有一般错误消息,仅说明传入的值未被识别为该类型的对象. 缺少特定错误是因为有必要知道值是 supposed 是 IPv4 还是 IPv6,以便提供有关拒绝的原因的更多详细信息。
为了支持访问此附加细节有用的用例,各个类构造函数实际上引发了 ValueError 子类 ipaddress.AddressValueError 和 ipaddress.NetmaskValueError准确指出定义的哪一部分未能正确解析。
直接使用类构造函数时,错误消息要详细得多。 例如:
但是,这两个特定于模块的异常都将 ValueError 作为它们的父类,因此如果您不关心特定类型的错误,您仍然可以编写如下代码: