python ipaddress模块简介

文章目录

  • 原著
  • 概述
  • 创建Address/Network/Interface
    • 1. IP地址
    • 2. 网段地址
    • 3. 主机接口(CIDR)
  • Address/Network/Interface成员函数
    • 获取ip地址的版本,ipv4或者ipv6:
    • 从ip地址获取网络地址:
    • 获取网段中地址数目:
    • ip_network.hosts迭代获取可用的主机地址(没有广播和0地址)
    • `netmask/hostmask`来获取网络/主机掩码:
    • ipv6简写/全写:
    • 网段作为一个列表
    • 比较
    • 转换成字符串/整数
  • 获取更多错误信息

原著

https://docs.python.org/3.7/howto/ipaddress.html

author: Peter Moody, Nick Coghlan

An introduction to the ipaddress module


概述

本文简单介绍了python自带的 ipaddress模块,只涉及了模块的基础部分,更多函数介绍,还是要参考模块的手册.


创建Address/Network/Interface

ipaddress模块是面向对象的。使用前先要创建相应对象。可以使用字符串或者整数来创建如下三种IP地址对象

注:此库支持ipv4和ipv6

1. IP地址

IP地址,或者叫主机地址,可以使用ipaddress.ip_address() 这个工厂类来创建,会根据传入的字符串自动的创建IPv4/IPv6地址:

>>> ipaddress.ip_address('192.0.2.1')
IPv4Address('192.0.2.1')
>>> ipaddress.ip_address('2001:DB8::1')
IPv6Address('2001:db8::1')

也可以使用正整数来创建地址,默认的,小于2^32认为是IPV4,大于则是IPv6地址:

>>> ipaddress.ip_address(3221225985)
IPv4Address('192.0.2.1')
>>> ipaddress.ip_address(42540766411282592856903984951653826561)
IPv6Address('2001:db8::1')

当然也可以用派生类IPv4Address/IPv6Address强制创建ipv4/ipv6地址:

>>> ipaddress.ip_address(1)
IPv4Address('0.0.0.1')
>>> ipaddress.IPv4Address(1)
IPv4Address('0.0.0.1')
>>> ipaddress.IPv6Address(1)
IPv6Address('::1')

2. 网段地址

ip/mask表示一个网段,可以使用ip_network创建IPv4/IPv6:

>>> ipaddress.ip_network('192.0.2.0/24')
IPv4Network('192.0.2.0/24')
>>> ipaddress.ip_network('2001:db8::0/96')
IPv6Network('2001:db8::/96')

一个网段地址中,主机地址不能被设置,比如192.0.2.1/24就不是一个有效的网段,初始化时程序会抛出一个 ValueError异常. 可以设置参数strict=False来自动的把主机地址置0:

>>> ipaddress.ip_network('192.0.2.1/24')
Traceback (most recent call last):
   ...
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')

如果使用一个整数来创建网段,则认为这个网段为单ip网段,掩码为32/128:

>>> ipaddress.ip_network(3221225984)
IPv4Network('192.0.2.0/32')
>>> ipaddress.ip_network(42540766411282592856903984951653826560)
IPv6Network('2001:db8::/128')

As with addresses, creation of a particular kind of network can be forced by calling the class constructor directly instead of using the factory function.

3. 主机接口(CIDR)

通常用cidr表示某个网络中的某台主机,比如192.0.2.1/24表示192.0.2.0/24网络中的主机192.0.2.1ipaddress模块提供了类接口ip_interface来定义一个主机cidr地址

>>> ipaddress.ip_interface('192.0.2.1/24')
IPv4Interface('192.0.2.1/24')
>>> ipaddress.ip_interface('2001:db8::1/96')
IPv6Interface('2001:db8::1/96')

Address/Network/Interface成员函数

用上面接口定义了IPv(4|6)(Address|Network|Interface)对象,可以调用下面的成员函数来获取对象的一些属性.

获取ip地址的版本,ipv4或者ipv6:

>>> addr4 = ipaddress.ip_address('192.0.2.1')
>>> addr6 = ipaddress.ip_address('2001:db8::1')
>>> addr6.version
6
>>> addr4.version
4

从ip地址获取网络地址:

>>> host4 = ipaddress.ip_interface('192.0.2.1/24')
>>> host4.network
IPv4Network('192.0.2.0/24')
>>> host6 = ipaddress.ip_interface('2001:db8::1/96')
>>> host6.network
IPv6Network('2001:db8::/96')

获取网段中地址数目:

>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> net4.num_addresses
256
>>> net6 = ipaddress.ip_network('2001:db8::0/96')
>>> net6.num_addresses
4294967296

ip_network.hosts迭代获取可用的主机地址(没有广播和0地址)

>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> for x in net4.hosts():
...     print(x)  
192.0.2.1
192.0.2.2
192.0.2.3
192.0.2.4
...
192.0.2.252
192.0.2.253
192.0.2.254

netmask/hostmask来获取网络/主机掩码:

>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> net4.netmask
IPv4Address('255.255.255.0')
>>> net4.hostmask
IPv4Address('0.0.0.255')
>>> net6 = ipaddress.ip_network('2001:db8::0/96')
>>> net6.netmask
IPv6Address('ffff:ffff:ffff:ffff:ffff:ffff::')
>>> net6.hostmask
IPv6Address('::ffff:ffff')

ipv6简写/全写:

>>> addr6.exploded
'2001:0db8:0000:0000:0000:0000:0000:0001'
>>> addr6.compressed
'2001:db8::1'
>>> net6.exploded
'2001:0db8:0000:0000:0000:0000:0000:0000/96'
>>> net6.compressed
'2001:db8::/96'

注:对于ipv4地址,依然提供这两个方法,只是不做处理,原值返回,这样代码可以不区分的调用而不会产生异常

网段作为一个列表

一个网段可以通过索引获取主机地址:

>>> net4 = ipaddress.ip_network('192.0.2.0/24')
>>> net4[1]
IPv4Address('192.0.2.1')
>>> net4[-1]
IPv4Address('192.0.2.255')
>>> net6[1]
IPv6Address('2001:db8::1')
>>> net6[-1]
IPv6Address('2001:db8::ffff:ffff')

可以判断某个ip是否在一个网段

# 参考代码
if address in network:
    # do something

可以写出如下优雅的代码

>>> addr4 = ipaddress.ip_address('192.0.2.1')
>>> addr4 in ipaddress.ip_network('192.0.2.0/24')
True
>>> addr4 in ipaddress.ip_network('192.0.3.0/24')
False

比较

ipaddress重载了>,<等比较运算符

>>> ipaddress.ip_address('192.0.2.1') < ipaddress.ip_address('192.0.2.2')
True

注:如果对比不是IPv4和IPv4或者和IPv6地址,会抛出TypeError异常

转换成字符串/整数

>>> addr4 = ipaddress.ip_address('192.0.2.1')
>>> str(addr4)
'192.0.2.1'
>>> int(addr4)
3221225985

获取更多错误信息

如果使用类工厂来创建IPv4/IPv6对象时,遇到错误,只会抛出 ValueError异常,因为类工厂不知道要创建哪种类,所以错误提示不是特别明确。如果想得到更多错误信息,可以使用原始IPv4/IPv6类来创建对象,这样会抛出ValueError的子类,比如ipaddress.AddressValueErroripaddress.NetmaskValueError来通知用户具体错误信息

The error messages are significantly more detailed when using the class constructors directly. For example:

>>> ipaddress.ip_address("192.168.0.256")
Traceback (most recent call last):
  ...
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):
  ...
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):
  ...
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):
  ...
ipaddress.NetmaskValueError: '64' is not a valid netmask

因为这两个类都有共同的父类ValueError,所以你可以写如下代码:

try:
    network = ipaddress.IPv4Network(address)
except ValueError:
    print('address/netmask is invalid for IPv4:', address)

你可能感兴趣的:(python)