python中处理IP地址

原文: http://my.oschina.net/taisha/blog/155224

IPy项目地址: https://github.com/haypo/python-ipy/

IPy - 提供了一些有用的类和函数来处理ipv6和ipv4地址和网络

API

IPy库包含类IP,使用它你可以方便处理对大部分格式的ipv6和ipv4网络和地址的格式化和处理。它的接口借鉴了Perl的NET::IP模块,但是实现上采用了不同的方法。它没有实现non-CIDR网络掩码,所以打算使用0xffffff0f格式网络掩码的无法使用。

    >>> from IPy import IP
    >>> ip = IP('127.0.0.0/30')
    >>> for x in ip:
    ...  print(x)
    ...
    127.0.0.0
    127.0.0.1
    127.0.0.2
    127.0.0.3
    >>> ip2 = IP('0x7f000000/30')
    >>> ip == ip2
    1
    >>> ip.reverseNames()
    ['0.0.0.127.in-addr.arpa.', '1.0.0.127.in-addr.arpa.', '2.0.0.127.in-addr.arpa.', '3.0.0.127.in-addr.arpa.']
    >>> ip.reverseName()
    '0-3.0.0.127.in-addr.arpa.'
    >>> ip.iptype()
    'PRIVATE'

支持大部分IP地址格式

它可以检测各种各样的ip地址和网络的格式,格式化他们并且区分他们是ipv4还是ipv6地址:

    >>> IP('10.0.0.0/8').version()
    4
    >>> IP('::1').version()
    6
#IPv4地址

    >>> print(IP(0x7f000001))
    127.0.0.1
    >>> print(IP('0x7f000001'))
    127.0.0.1
    >>> print(IP('127.0.0.1'))
    127.0.0.1
    >>> print(IP('10'))
    10.0.0.0

#IPv6地址

    >>> print(IP('1080:0:0:0:8:800:200C:417A'))
    1080::8:800:200c:417a
    >>> print(IP('1080::8:800:200C:417A'))
    1080::8:800:200c:417a
    >>> print(IP('::1'))
    ::1
    >>> print(IP('::13.1.68.3'))
    ::d01:4403

网络掩码和前缀

    >>> print(IP('127.0.0.0/8'))
    127.0.0.0/8
    >>> print(IP('127.0.0.0/255.0.0.0'))
    127.0.0.0/8
    >>> print(IP('127.0.0.0-127.255.255.255'))
    127.0.0.0/8

推导网络地址

IPy可以通过使用一个网络掩码将一个IP地址转化为网络地址:

>>> print(IP('127.0.0.1/255.0.0.0', make_net=True))
127.0.0.0/8

也可以直接操作一个IP对象:

>>> print(IP('127.0.0.1').make_net('255.0.0.0'))
127.0.0.0/8

转化成字符串

基本上所有的返回一个字符串的类方法都会有一个可选参数'wantprefixlen',它用来控制是否打印前缀或者网络掩码。如果网络地址包含多个地址,那么默认情况下总会显示前缀的:

    wantprefixlen == 0 / None     don't return anything   1.2.3.0
    wantprefixlen == 1            /prefix                 1.2.3.0/24
    wantprefixlen == 2            /netmask                1.2.3.0/255.255.255.0
    wantprefixlen == 3            -lastip                 1.2.3.0-1.2.3.255

你可以通过改变下面这些对象属性来改变默认行为:

字符串转化例子:

    >>> IP('10.0.0.0/32').strNormal()
    '10.0.0.0'
    >>> IP('10.0.0.0/24').strNormal()
    '10.0.0.0/24'
    >>> IP('10.0.0.0/24').strNormal(0)
    '10.0.0.0'
    >>> IP('10.0.0.0/24').strNormal(1)
    '10.0.0.0/24'
    >>> IP('10.0.0.0/24').strNormal(2)
    '10.0.0.0/255.255.255.0'
    >>> IP('10.0.0.0/24').strNormal(3)
    '10.0.0.0-10.0.0.255'
    >>> ip = IP('10.0.0.0')
    >>> print(ip)
    10.0.0.0
    >>> ip.NoPrefixForSingleIp = None
    >>> print(ip)
    10.0.0.0/32
    >>> ip.WantPrefixLen = 3
    >>> print(ip)
    10.0.0.0-10.0.0.0

处理多个网络地址

只是简单的添加一个相邻的网络地址块可以聚集成一个包含两个网络地址块的网络地址,但是要想处理更加复杂的网络地址聚集和映射情况,可以使用IPSet类,它可以保存任意个网络地址块。

    >>> from IPy import IP, IPSet
    >>> IP('10.0.0.0/22') - IP('10.0.2.0/24')
    IPSet([IP('10.0.0.0/23'), IP('10.0.3.0/24')])

    >>> IPSet([IP('10.0.0.0/23'), IP('10.0.3.0/24'), IP('10.0.2.0/24')])
    IPSet([IP('10.0.0.0/22')])

    >>> s = IPSet([IP('10.0.0.0/22')])
    >>> s.add(IP('192.168.1.0/29'))
    >>> s
    IPSet([IP('10.0.0.0/22'), IP('192.168.1.0/29')])
    >>> s.discard(IP('192.168.1.2'))
    >>> s
    IPSet([IP('10.0.0.0/22'), IP('192.168.1.0/31'), IP('192.168.1.3'), IP('192.168.1.4/30')])

兼容性和一些链接

IPy 0.82兼容Python 2.6 - 3.3版本.

如何不是用减法,IP模块也可以在python2.5中使用,IPSet需要使用python2.6中的collections模块。