Python的netaddr模块使用记录


=Start=

缘由:

前段时间因为工作上的需求,需要写一个小工具处理IP地址相关的问题,用shell写的话太复杂而且程序不易维护和移植,所以决定用Python来处理。考虑到Python中已经有很多现成的模块可以用来进行IP地址的处理,在搜索比较了几个之后选择了netaddr模块。下面就是使用过程的记录,记录至此做个备忘。

 正文:
0.安装

https://pypi.python.org/pypi/netaddr

$ pip search netaddr
$ sudo -H pip install netaddr

1.简单的使用
In [1]: from netaddr import *

In [2]: ip = IPNetwork('192.0.2.5/24')

In [3]: ip.
#下面仅列出一些我常用的方法/函数
ip.broadcast  #IP段的广播地址
ip.cidr  #IP段的CIDR形式
ip.netmask  #IP段的网络掩码
ip.first  #IP段的起始IP地址——以整数形式表示
ip.last  #IP段的结束IP地址——以整数形式表示
ip.size  #IP段的大小(包含多少个IP地址)
ip.value  #IP地址——以整数形式表示
ip.ip  #IP地址
ip.network  #IP所在网段

In [3]: type(ip), ip
Out[3]: (netaddr.ip.IPNetwork, IPNetwork('192.0.2.5/24'))

In [4]: ip.first, ip.last
Out[4]: (3221225984, 3221226239)

In [5]: ip.broadcast, ip.network
Out[5]: (IPAddress('192.0.2.255'), IPAddress('192.0.2.0'))

In [7]: ip.broadcast, ip.network, ip.netmask, ip.hostmask
Out[7]:
(IPAddress('192.0.2.255'),
IPAddress('192.0.2.0'),
IPAddress('255.255.255.0'),
IPAddress('0.0.0.255'))

In [8]: ip.ip
Out[8]: IPAddress('192.0.2.5')

In [9]: ip.value
Out[9]: 3221225989

In [11]: ip.ip.bits()
Out[11]: '11000000.00000000.00000010.00000101'

In [12]: ip.size
Out[12]: 256

In [14]: ip.netmask.value  #IP段子网掩码值的十进制整数格式
Out[14]: 4294967040

In [15]: ip.netmask.words
Out[15]: (255, 255, 255, 0)
2.netaddr模块提供的高级功能

https://pythonhosted.org/netaddr/tutorial_03.html

3.使用实例

从某一IP段中排除指定的IP地址、IP区间(同时支持「CIDR」和「192.168.1.1-192.168.1.5」这两种格式),代码如下:

#!/usr/bin/env python
# coding=utf-8
import sys, time
from netaddr import *

def main():
    ipset = IPSet()
    ipset.add(sys.argv[1].strip())
    for item in sys.argv[2:]:
        if "-" in item:
            ipset.remove(IPRange(item.split("-")[0], item.split("-")[1]))
        else:
            ipset.remove(item)
    for item in ipset.iter_ipranges():
        print item

if __name__ == '__main__':
    time_start = time.time()
    try:
        main()
    except KeyboardInterrupt:
        print 'Killed by user'
        sys.exit(0)
    print "\nSpend {0} seconds.\n".format(time.time() - time_start)

=END=


《 “Python的netaddr模块使用记录” 》 有 6 条评论

  1. ipaddress — IPv4/IPv6 manipulation library
    https://docs.python.org/3/library/ipaddress.html
    https://docs.python.org/zh-cn/3/howto/ipaddress.html
    `
    判断某个IP是否在某个IP段内:
    # 先基于字符串格式的IP生成一个ip_address对象,然后再判断这个对象是否在ip_network这个对象内即可
    >>> 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
    `

  2. 为什么上面的Python代码不将192.168.121.0-192.168.121.254这255个IP列表合并成192.168.121.0/24这个CIDR格式?

    而是返回:
    192.168.121.0/25
    192.168.121.128/26
    192.168.121.192/27
    192.168.121.224/28
    192.168.121.240/29
    192.168.121.248/30
    192.168.121.252/31
    192.168.121.254/32

    因为一个/24的CIDR格式IPv4地址段包含的是256个IP,而上面的只有255个IP,因为缺少一个IP,所以没办法浓缩成1个CIDR地址段,而是需要多个CIDR地址段进行准确表示。

  3. 在Python3中用netaddr模块来实现,读取cidr格式的IP列表文件,然后输出为每行一个IP地址的功能。

    使用Python3自带的ipaddress模块测试的时候发现了bug,比如上面的,将下面这些CIDR格式的IP地址段还原成具体的IP地址列表时,会有一些随机的错漏,具体原因不详,有点坑,后面还是要注意。

    192.168.121.0/25
    192.168.121.128/26
    192.168.121.192/27
    192.168.121.224/28
    192.168.121.240/29
    192.168.121.248/30
    192.168.121.252/31
    192.168.121.254/32

    代码可以用通义千问等LLM大模型来生成,简单改改就能用。

回复 hi 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注