在日常网络规划中,会有很多关于IP地址的分配规划问题,如果是手动分配,在量很大的情况下,容易出错。而利用IPy这个python模块,可以很容易实现对iP地址的分配等操作。
以下是对IPy模块学习的一个记录。
IPy模块简介
主要用处:
IPy-用于处理IPv4和IPv6地址和网络的类和工具。
IPy相关:
IPy源码: https://github.com/autocracy/python-ipy/
IPy类和方法
IPy主要有如下类和方法:
dir(IPy) Out[8]: ['INT_TYPES', 'IP', 'IPSet', 'IPV6_MAP_MASK', 'IPV6_TEST_MAP', 'IPint', 'IPv4ranges', 'IPv6ranges', 'MAX_IPV4_ADDRESS', 'MAX_IPV6_ADDRESS', 'STR_TYPES', '_BitTable', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '__version__', '_checkNetaddrWorksWithPrefixlen', '_checkNetmask', '_checkPrefix', '_count0Bits', '_count1Bits', '_countFollowingZeros', '_intToBin', '_ipVersionToLen', '_netmaskToPrefixlen', '_parseAddressIPv6', '_prefixlenToNetmask', '_remove_subprefix', 'bisect', 'collections', 'intToIp', 'parseAddress', 'sys', 'types', 'xrange']
其中有IPint,IP,IPSet是三个类。
一般都使用IP类,IP类是IPint的代替,IP类继承IPint类。
INT_TYPES,IPV6_MAP_MASK,IPV6_TEST_MAP,IPv4ranges, IPv6ranges,MAX_IPV4_ADDRESS,MAX_IPV6_ADDRESS,STR_TYPES这都是定义的常量。
IPint类 class IPint(object):
处理返回整数的IP地址。
因为IP类继承自IPint,所以IPint类中的方法在IP类中同样适用。
下面会记录常用方法。
__init__(self, data, ipversion=0, make_net=0)
- data可以是常见的IPv4和IPv6地址的各种表现形式。支持前缀表示,IP段表示,小数点掩码表示,单个IP等。
也可以输入10进制的进制,2进制的地址等。
- ipversion可以制定地址的版本,版本为4或者6,输入其他会报错。
- mask_net如果是为Ture,则可以通过指定掩码来分配IP地址。
测试如下:
>>> 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 >>> print(IP('127.0.0.1/255.0.0.0', make_net=True)) 127.0.0.0/8 [39]: from IPy import IPint ip = IPint('192.168.1.0/24',make_net=True) ip Out[41]: IPint('192.168.1.0/24') for x in ip: print(x) #返回的是整数类型的IP地址。 ...
常用方法:
#实例化一个IP地址 ip = IPint('192.168.1.0/24') ip.int() #返回第一个长整型的IP地址 Out[52]: ip.version() #返回ip的版本号 Out[53]: 4 ip.prefixlen() #返回掩码长度 Out[54]: 24 ip.net() #返回第一个长整型的IP地址 Out[55]: ip.broadcast() #返回长整型的广播地址 Out[56]: ----------------------------------------- _printPrefix(self, want): #按输入的want打印掩码 ip._printPrefix(0) #want == 0,None,什么也不返回 Out[58]: '' ip._printPrefix(1) #want == 1, 返回前缀形式的掩码 Out[59]: '/24' ip._printPrefix(2) #want == 2,返回小数点的掩码 Out[60]: '/255.255.255.0' ip._printPrefix(3) #want == 3,返回网络号的最后一个地址 Out[61]: '-192.168.1.255' ipv6 = IPint('2003::/64') ipv6._printPrefix Out[70]: <bound method IPint._printPrefix of IPint('2003::/64')> ipv6._printPrefix(0) Out[71]: '' ipv6._printPrefix(1) Out[72]: '/64' ipv6._printPrefix(2) Out[73]: '/ffff:ffff:ffff:ffff:0000:0000:0000:0000' ipv6._printPrefix(3) Out[74]: '-2003:0000:0000:0000:ffff:ffff:ffff:ffff' -------------------------------------- #可以将IP地址转化为多种类型的字符串。 ipv6.strBin() #返会IPv4或者IPv6的2进制形式字符串 Out[79]: '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' ipv6.strCompressed() #返会简写的形式的地址,主要针对IPv6有效果 Out[80]: '2003::/64' ipv6.strDec() #返会10进制的地址形式 Out[81]: '86720' ipv6.strFullsize() #返会完整形式的地址格式。 Out[82]: '2003:0000:0000:0000:0000:0000:0000:0000/64' ipv6.strHex() #返会16进制形式的地址 Out[83]: '0x000000000000000000000' ipv6.strNetmask() #返会掩码长度 Out[84]: '/64' ipv6.strNormal(wantprefixlen = None) #可以按输入的wantprefixlen来转化为字符串 ipv6.strNormal(wantprefixlen = 0) #不输出掩码 Out[92]: '2003:0:0:0:0:0:0:0' ipv6.strNormal((wantprefixlen = 1) #输出前缀掩码 Out[93]: '2003:0:0:0:0:0:0:0/64' ipv6.strNormal((wantprefixlen = 2) #输出网络掩码 Out[94]: '2003:0:0:0:0:0:0:0/ffff:ffff:ffff:ffff:0000:0000:0000:0000' ipv6.strNormal(3) #输出地址段 Out[95]: '2003:0:0:0:0:0:0:0-2003:0000:0000:0000:ffff:ffff:ffff:ff --------------------------------------- ip.iptype() #返会IP地址的类型 Out[98]: 'PRIVATE' ip2 = IPint('1.1.1.1') ip2.iptype() Out[100]: 'PUBLIC' print(IP('127.0.0.1').iptype()) Out[101]: LOOPBACK print(IP('::1').iptype()) Out[102]: LOOPBACK print(IP('2001:0658:022a:cafe:0200::1').iptype()) Out[103]: ALLOCATED RIPE NCC ----------------------------------------- ip.netmask() #返会整型形式的掩码 Out[104]: ip.strNetmask() #返会字符串形式的掩码 Out[105]: '255.255.255.0' ip.len() #返会子网的长度 Out[106]: 256 IP('10.1.1.0/28').len() Out[108]: 16 ---------------------------------------- ip.__getitem__(1) #返会网络号中第i个地址。 Out[120]: ip.__getitem__(2) Out[121]: ip.__getitem__(3) Out[122]: ip Out[124]: IPint('192.168.1.0/24') ip.__contains__('192.168.1.1') #判断一个地址是否在这个网段中 Out[125]: True ip.__contains__('192.168.2.1') Out[126]: False '192.168.1.1' in ip Out[127]: True '192.168.3.1' in ip Out[128]: False ------------------------------------------ #检查给定IP地址是否在这个实例化的IP地址返回内 def overlaps(self, item): #如果不重叠,返会0; #如果给定地址在这个实例化的IP地址范围内返会1. #如果给定地址在不这个实例化的IP地址范围内返会-1. IP('192.168.1.0/24').overlaps('192.168.1.254') Out[131]: 1 IP('192.168.1.0/24').overlaps('192.168.2.254') Out[132]: 0 IP('192.168.1.0/24').overlaps('192.168.0.0/16') Out[134]: -1 ---------------------------------------- #实例化后的两个IP地址可以进行比较,IPv4总是小于IPv6地址,第一个地址总是小的。 掩码短的小于掩码长的 #如果self < other,返会-1, 如果self == other,返会0,如果self > other,返会1. ip Out[158]: IPint('192.168.1.0/24') ip2 Out[159]: IPint('1.1.1.1') ip3 Out[160]: IP('192.0.0.0/8') ipv6 Out[161]: IPint('2003::/64') ip4 = IP('192.168.1.0/24') ip.__cmp__(ip4) Out[163]: 0 ip.__cmp__(ip3) Out[166]: 1 ip.__cmp__(ipv6) Out[168]: -1 ip > ip2 Out[177]: True ip < ip2 Out[178]: False ip == i
IP类,class IP(IPint):
IP类继承自IPint,所以IP类具有IPint的所有方法。
IP类主要处理IP地址和网络。IP类与IPint相比,返会的不再是整数型值,而是网络形式的字符串。
ipint = IPint('192.168.1.0/24') ip = IP('192.168.1.0/24') ipint.net() Out[197]: ip.net() #返回网络地址 Out[198]: IP('192.168.1.0') ip.broadcast() #返会广播地址 Out[199]: IP('192.168.1.255') ipint.broadcast() Out[200]: ip.netmask() #返会网络掩码 Out[201]: IP('255.255.255.0') ip.reverseName() Out[207]: '1.168.192.in-addr.arpa.' ip.reverseNames() #返会用于反向查找的列表值。 Out[208]: ['1.168.192.in-addr.arpa.'] IP('213.221.112.224/30').reverseNames() Out[209]: ['224.112.221.213.in-addr.arpa.', '225.112.221.213.in-addr.arpa.', '226.112.221.213.in-addr.arpa.', '227.112.221.213.in-addr.arpa.'] IP('::1:2').reverseNames() Out[211]: ['2.0.0.0.1.ip6.arpa.'] IP('213.221.112.224/30').reverseName() #返会用于反向查找的一个字符串,而不是列表。 Out[217]: '224-227.112.221.213.in-addr.arpa.' IP('10.1.1.1').make_net(24) #对于单个IP地址,可以加上掩码,返会新的IP地址实例 Out[231]: IP('10.1.1.0/24') ip Out[235]: IP('192.168.1.0/24') ip.__getitem__(1) #返回网络号中的地i个地址 Out[236]: IP('192.168.1.1')
IPSet类,IPSet(collections.MutableSet):
可以用来对网段进行汇总。
IPSet仅仅接收IP实例的对象。
IPSet的值是存在列表中。
from IPy import IPSet from IPy import IP ipset = IPSet() #实例化一个IPSet对象 ipset.add(IP('192.168.1.0/24')) #给IPSet集合中添加一个网段 ipset Out[301]: IPSet([IP('192.168.1.0/24')]) ipset.add([IP('192.168.2.0/24'),IP('192.168.3.0/24')]) ipset #以列表形式添加多个网段 Out[303]: IPSet([IP('192.168.1.0/24'), IP('192.168.2.0/23')]) ipset.add(IP('192.168.0.0/16')) ipset#会对已有的所有网段进行汇总 Out[308]: IPSet([IP('192.168.0.0/16')]) ipset.discard(IP('192.168.1.0/24')) #移除汇总网段中某个网段 ipset Out[310]: IPSet([IP('192.168.0.0/24'), IP('192.168.2.0/23'), IP('192.168.4.0/22'), IP('192.168.8.0/21'), IP('192.168.16.0/20'), IP('192.168.32.0/19'), IP('192.168.64.0/18'), IP('192.168.128.0/17')]) n [317]: ipset2 = IPSet() ipset2.add(IP('192.168.1.0/24')) ipset2 Out[319]: IPSet([IP('192.168.1.0/24')]) ipset.isdisjoint(ipset2) #判断某个集合中的网段是否在现有集合网段中 Out[320]: True ipset3 = IPSet() ipset3.add(IP('192.168.2.0/24')) ipset.isdisjoint(ipset3) Out[323]: False ipset.__contains__(IP('192.168.2.0/24')) #判断某个网段是否在现有汇总网段中 Out[335]: True
IPy中的其他常用方法:
def _parseAddressIPv6(ipstr): #将IPv6字符串解析为十进制的整型数据 ipv6 = IPy._parseAddressIPv6('1080:200C::1') ipv6 Out[345]: 42049 IP(ipv6) Out[346]: IP('1080:200c::1') def parseAddress(ipstr, ipversion=0):#解析IP地址 IPy.parseAddress('192.168.1.1') Out[348]: (, 4) IPy.parseAddress('123.132')#不够的后面加0补齐 Out[349]: (, 4) IPy.intToIp(, version=4) Out[351]: '192.168.1.1' def intToIp(ip, version): #将整型的IP地址转化为字符串IP地址 IPy.intToIp(, version=6) Out[352]: '0000:0000:0000:0000:0000:0000:c0a8:0101' def _intToBin(val): #将int型的地址转化为二进制 IPy._intToBin(13241) Out[360]: '001'
利用IPy写的小程序:
批量分配指定掩码和分配个数的IPv4或者IPv6地址:
通过下面的程序,可以指定开始的一个IPv4或者IPv6地址,然后指定掩码,指定需要生成的网段个数,就可以通过程序批量分配地址。
地址输出格式,可以根据需要,灵活定义。
# -*- coding: utf-8 -*- """ Created on Sun Dec 1 21:51:11 2019 @author: cao """ import IPy def get_ip_list(begin_ip, count, netmask): ip_list = '' #用来存放生成的IP地址 begin_ip = IPy.IP(begin_ip) ip_list += str(begin_ip) + '\n' #将第一个地址放入ip_列表中 if begin_ip.version() == 4: for i in range(count): ip = IPy.IP(begin_ip) new_ip = IPy.IP(ip.ip + 2 (32 - netmask)) begin_ip = str(new_ip) ip_list += begin_ip + '\n' else: for i in range(count): ipv6 = IPy.IP(begin_ip) new_ipv6 = IPy.IP(ipv6.ip + 2 (128 - netmask)) begin_ip = str(new_ipv6) ip_list += begin_ip + '\n' return ip_list if __name__ == "__main__": ipv6_list = get_ip_list(begin_ip = '2002::', count=10, netmask=64) print('批量分配业务IPv6地址:') print('============================') print(ipv6_list) ipv6_list2 = get_ip_list(begin_ip = 'FD00:0:2e3f::', count=10, netmask=127) print('批量分配互联IPv6地址:') print('============================') print(ipv6_list2) ip_list = get_ip_list(begin_ip='192.168.1.0', count=10,netmask=24) print('批量分配业务IPv4地址:') print('============================') print(ip_list) ip_list2 = get_ip_list(begin_ip='192.168.2.0', count = 10, netmask=30) print('批量分配互联IPv4地:') print('============================') print(ip_list2)
程序运行结果:
批量分配业务IPv6地址: ============================ 2002:: 2002:0:0:1:: 2002:0:0:2:: 2002:0:0:3:: 2002:0:0:4:: 2002:0:0:5:: 2002:0:0:6:: 2002:0:0:7:: 2002:0:0:8:: 2002:0:0:9:: 2002:0:0:a:: 批量分配互联IPv6地址: ============================ fd00:0:2e3f:: fd00:0:2e3f::2 fd00:0:2e3f::4 fd00:0:2e3f::6 fd00:0:2e3f::8 fd00:0:2e3f::a fd00:0:2e3f::c fd00:0:2e3f::e fd00:0:2e3f::10 fd00:0:2e3f::12 fd00:0:2e3f::14 批量分配业务IPv4地址: ============================ 192.168.1.0 192.168.2.0 192.168.3.0 192.168.4.0 192.168.5.0 192.168.6.0 192.168.7.0 192.168.8.0 192.168.9.0 192.168.10.0 192.168.11.0 批量分配互联IPv4地: ============================ 192.168.2.0 192.168.2.4 192.168.2.8 192.168.2.12 192.168.2.16 192.168.2.20 192.168.2.24 192.168.2.28 192.168.2.32 192.168.2.36 192.168.2.40
可将批量生成的IP地址直接复制到Excel表格,或者文件中,用作后续批量生成网络设备配置等。
按固定格式批量分配掩码为64位的IPv6地址:
在网络规划中,需要给业务分配IPv6地址时,假设掩码都是64。同时需要给出IPv6对应的网关地址。
以下程序,给出一个开始的IPv6地址,然后指定count需要分配多少个地址。就会打印出指定数量的IPv6地址,同时给错每个地址对应的指定的网关地址。
# -*- coding: utf-8 -*- """ Created on Tue Nov 26 16:04:36 2019 @author: cao """ #批量计算业务网段,默认按掩码64位计算 import IPy #按冒号分割后,判断段是否满足4位,不是前面补零 #这个是为了分下来地址格式比较规整。可以不需要。 def add_0(tmp): if len(tmp) == 3: tmp = '0' + tmp elif len(tmp) == 2: tmp = '00' + tmp elif len(tmp) == 1: tmp = '000' + tmp else: pass return tmp #传入一个IPv6地址,进项每段0的填充 def ipv6_format(ipv6): tmp_ip = '' for i in ipv6.split(':'): if(len(i) == 0): continue if(i == '0'): tmp_ip += '0:' continue tmp_ip += add_0(i) + ':' return tmp_ip + ':' #获取业务网段IPv6对应的网关地址 def ipv6_GW(ipv6_list): ip_list_gw = '' for ip_net in ipv6_list.split('\n'): if(len(ip_net) == 0): break ip_list_gw += ip_net + 'FFFF\n' return ip_list_gw if __name__ == "__main__": begin_ip = 'FD00:0:0004:009B::' ipv6_count = 10 ipv6_list = begin_ip + '\n' #业务网段地址 ipv6_gw = '' #业务网段对应的网关 for i in range(ipv6_count): ipv6 = IPy.IP(begin_ip) new_ipv6 = str.upper(str(IPy.IP(ipv6.ip + 264))) begin_ip = ipv6_format(new_ipv6) ipv6_list += begin_ip + '\n' print(ipv6_list) ipv6_gw = ipv6_GW(ipv6_list) print(ipv6_gw)
程序运行结果:
FD00:0:0004:009B:: FD00:0:0004:009C:: FD00:0:0004:009D:: FD00:0:0004:009E:: FD00:0:0004:009F:: FD00:0:0004:00A0:: FD00:0:0004:00A1:: FD00:0:0004:00A2:: FD00:0:0004:00A3:: FD00:0:0004:00A4:: FD00:0:0004:00A5:: FD00:0:0004:009B::FFFF FD00:0:0004:009C::FFFF FD00:0:0004:009D::FFFF FD00:0:0004:009E::FFFF FD00:0:0004:009F::FFFF FD00:0:0004:00A0::FFFF FD00:0:0004:00A1::FFFF FD00:0:0004:00A2::FFFF FD00:0:0004:00A3::FFFF FD00:0:0004:00A4::FFFF FD00:0:0004:00A5::FFFF
得到想要地址后,可以直接复制到Excel表格中,或者直接写到文件中。用于后续批量生成配置。
至于输出的IPv6地址格式,或者IPv4地址格式,可以根据需要灵活控制。
参考资料:
https://pypi.org/project/IPy/
IPy源码: https://github.com/autocracy/python-ipy/
https://zhuanlan.zhihu.com/p/
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/201827.html原文链接:https://javaforall.net
