11.4 通过CIDR地址生成对应的IP地址集

问题

你有一个CIDR网络地址比如“123.45.67.89/27”,你想将其转换成它所代表的所有IP(比如,“123.45.67.64”, “123.45.67.65”, …, “123.45.67.95”))

解决方案

可以使用 ipaddress 模块很容易的实现这样的计算。例如:

  1. >>> import ipaddress
  2. >>> net = ipaddress.ip_network('123.45.67.64/27')
  3. >>> net
  4. IPv4Network('123.45.67.64/27')
  5. >>> for a in net:
  6. ... print(a)
  7. ...
  8. 123.45.67.64
  9. 123.45.67.65
  10. 123.45.67.66
  11. 123.45.67.67
  12. 123.45.67.68
  13. ...
  14. 123.45.67.95
  15. >>>
  16.  
  17. >>> net6 = ipaddress.ip_network('12:3456:78:90ab:cd:ef01:23:30/125')
  18. >>> net6
  19. IPv6Network('12:3456:78:90ab:cd:ef01:23:30/125')
  20. >>> for a in net6:
  21. ... print(a)
  22. ...
  23. 12:3456:78:90ab:cd:ef01:23:30
  24. 12:3456:78:90ab:cd:ef01:23:31
  25. 12:3456:78:90ab:cd:ef01:23:32
  26. 12:3456:78:90ab:cd:ef01:23:33
  27. 12:3456:78:90ab:cd:ef01:23:34
  28. 12:3456:78:90ab:cd:ef01:23:35
  29. 12:3456:78:90ab:cd:ef01:23:36
  30. 12:3456:78:90ab:cd:ef01:23:37
  31. >>>

Network 也允许像数组一样的索引取值,例如:

  1. >>> net.num_addresses
  2. 32
  3. >>> net[0]
  4.  
  5. IPv4Address('123.45.67.64')
  6. >>> net[1]
  7. IPv4Address('123.45.67.65')
  8. >>> net[-1]
  9. IPv4Address('123.45.67.95')
  10. >>> net[-2]
  11. IPv4Address('123.45.67.94')
  12. >>>

另外,你还可以执行网络成员检查之类的操作:

  1. >>> a = ipaddress.ip_address('123.45.67.69')
  2. >>> a in net
  3. True
  4. >>> b = ipaddress.ip_address('123.45.67.123')
  5. >>> b in net
  6. False
  7. >>>

一个IP地址和网络地址能通过一个IP接口来指定,例如:

  1. >>> inet = ipaddress.ip_interface('123.45.67.73/27')
  2. >>> inet.network
  3. IPv4Network('123.45.67.64/27')
  4. >>> inet.ip
  5. IPv4Address('123.45.67.73')
  6. >>>

讨论

ipaddress 模块有很多类可以表示IP地址、网络和接口。当你需要操作网络地址(比如解析、打印、验证等)的时候会很有用。

要注意的是,ipaddress 模块跟其他一些和网络相关的模块比如 socket 库交集很少。所以,你不能使用 IPv4Address 的实例来代替一个地址字符串,你首先得显式的使用 str() 转换它。例如:

  1. >>> a = ipaddress.ip_address('127.0.0.1')
  2. >>> from socket import socket, AF_INET, SOCK_STREAM
  3. >>> s = socket(AF_INET, SOCK_STREAM)
  4. >>> s.connect((a, 8080))
  5. Traceback (most recent call last):
  6. File "<stdin>", line 1, in <module>
  7. TypeError: Can't convert 'IPv4Address' object to str implicitly
  8. >>> s.connect((str(a), 8080))
  9. >>>

更多相关内容,请参考 An Introduction to the ipaddress Module

原文:

http://python3-cookbook.readthedocs.io/zh_CN/latest/c11/p04_generate_range_of_ip_addresses_from_cidr_address.html