PythonでIPアドレスを簡単に扱う方法
IPアドレスってプログラムから扱おうとするとめんどくさいですよね
数字だけならいいのですが、たいてい192.168.0.2
とか間にドットが入ってくる
またサブネットもオクテット刻みであればドットごとに分けて数字として計算すれば加算、減算できますが/23
とか
半端な値になると結構めんどくさいです。
2点間のIPレンジの一覧が欲しい時、以下のように書いていました
# 2IPアドレス間の一覧を列挙する # start_ip '192.168.0.' end_ip '192.168.2.5' subnet '255.255.254.0' def generate_ipaddr_list(start_ip,end_ip,subnet): start_ip_list = [int(i) for i in start_ip.split('.')] end_ip_list = [int(i) for i in end_ip.split('.')] subnet_list = [int(i) for i in subnet.split('.')] int_mask = ip_to_binip(subnet).count('1') result_ips = [] try: for oct1_ip in range(start_ip_list[0],end_ip_list[0]+1): for oct2_ip in range(start_ip_list[1],end_ip_list[1]+1): for oct3_ip in range(start_ip_list[2],end_ip_list[2]+1): for oct4_ip in range(start_ip_list[3],end_ip_list[3]+1): ip_l = [oct1_ip,oct2_ip,oct3_ip,oct4_ip] ip_str = '.'.join([str(i )for i in ip_l]) if ip_l <= end_ip_list and ip_to_binip(ip_str)[:int_mask] == ip_to_binip(start_ip)[:int_mask]: result_ips.append(ip_str) else: raise Exception except Exception: pass finally: return result_ips # 10進数のIPをバイナリ形式に変換 def ip_to_binip(str_ip): str_ip_list = [int(i) for i in str_ip.split('.')] b_str_ip = '' for s in str_ip_list: b_str_ip += format(s,'b').zfill(8) return b_str_ip
一度バイナリ形式に変換してから計算する仕組みです。 Pythonでバイナリ型はIP計算で使いたいような算術演算がないので使いにくいです
計算しにくいなーと思っていたら、そもそもPythonにipaddressってモジュールがありました
使い方
import ipaddress as ip start_ip = ip.IPv4Address('192.168.0.100') end_ip = ip.IPv4Address('192.168.3.100') # 特定のIPアドレス間の一覧を表示 i = 0 while start_ip + i <= end_ip: now_ip = start_ip + i print(now_ip.exploded) i += 1 # =< 192.168.0.100 ,192.168.0.101 ... ,192.168.3.100 # ネットワークセグメントのIP一覧 for addr in ip.IPv4Network('192.168.0.0/23'): # 255.255.254.0でも可 print(addr.exploded) # IPアドレスがプライベートか否か start_ip.is_private # =>True # 2進数へ変換 start_ip.packed # => True test_ip = ip.IPv4Interface('192.168.2.100') # IPv4Networkオブジェクトを生成 IPを指定していないと/32 test_ip.network # => IPv4Network('192.168.2.100/32') # /XXの形 test_ip.with_prefixlen # => '192.168.2.100/32' # /255.255 ~の形 test_ip.with_netmask # => '192.168.2.100/255.255.255.255'
IPv4InterfaceクラスはIPv4Addressクラスのサブクラスのため、特に問題なければIPv4Interfaceクラスでオブジェクト生成したほうがいいかもしれません