0
2

More than 1 year has passed since last update.

pythonでIPアドレスを扱う方法

Posted at

概要

  • pythonでIPアドレスを扱う方法を記載します

TL;DR

  • ipアドレス型は、str型やint型に変換できる
  • ipアドレスの計算はint型の方が約2倍程度早かった

pythonのIP-Addressモジュールでできること

  • ip addressの形になっているかチェック
  • str型やint型に変換
  • 2つのip addressの計算
    • subnet_of
    • supernet_of
  • 内包しているipの確認

IP-Address型に変換

  • ipaddress モジュールは簡単に IP アドレス、ネットワーク、インターフェースを生成する

  • >>> import ipaddress
    >>> ipaddress.ip_network('192.168.0.0/24')
    IPv4Network('192.168.0.0/24')
    >>> ipaddress.ip_address('192.168.0.1')
    IPv4Address('192.168.0.1')
    
  • エラーになる例

    • ip_address192.168.0.1/24を与えると「IPv4またはIPv6アドレスではない」と怒られます
      • 対策:prefix(/24)を削除するもしくは/32にする
    • ip_network192.168.0.255/24を与えると「192.168.0.1/24はホストビットが設定されている」と怒られます
      • 対策:第4オクテットを0にする
    >>> ipaddress.ip_address('192.168.0.1/24')
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ipaddress.py", line 54, in ip_address
            raise ValueError('%r does not appear to be an IPv4 or IPv6 address' %
        ValueError: '192.168.0.1/24' does not appear to be an IPv4 or IPv6 address
    >>> ipaddress.ip_network('192.168.0.255/24')
        Traceback (most recent call last):
          File "<stdin>", line 1, in <module>
          File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ipaddress.py", line 75, in ip_network
            return IPv4Network(address, strict)
          File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/ipaddress.py", line 1510, in __init__
            raise ValueError('%s has host bits set' % self)
        ValueError: 192.168.0.255/24 has host bits set
    

str型やint型に変換

  • 変換例
    • str型

      >>> str(ipaddress.ip_address('192.168.0.1'))
      '192.168.0.1'
      >>> type(str(ipaddress.ip_address('192.168.0.1')))
      <class 'str'>
      >>> type(ipaddress.ip_address('192.168.0.1'))
      <class 'ipaddress.IPv4Address'>
      
    • int型

      >>> int(ipaddress.ip_address('192.168.0.1'))
      3232235521
      >>> type(int(ipaddress.ip_address('192.168.0.1')))
      <class 'int'>
      >>> type(ipaddress.ip_address('192.168.0.1'))
      <class 'ipaddress.IPv4Address'>
      

2つのip addressの計算

IPアドレス型通しの計算

subnet_of

  • サブネットを簡単に説明すると
    大きなネットワークを分割した際の、それぞれの小さいネットワーク
  • 例のip b例のip aのサブネットだった場合にTrueとなる
    • 構文: b_ip.subnet_of(a_ip)
    • b_ipがa_ipのサブネット(小さいネットワーク)であればTrueを返す
>>> a_ip = ipaddress.ip_network('192.168.0.0/24')
>>> b_ip = ipaddress.ip_network('192.168.0.16/28')
>>> b_ip.subnet_of(a_ip)
True
>>> a_ip.subnet_of(b_ip)
False

supernet_of

  • スーパネットを簡単に説明すると
    小さなネットワークを合体させて1つの大きなネットワークにすること
    • サブネットの逆です
>>> a_ip = ipaddress.ip_network('192.168.0.0/24')
>>> b_ip = ipaddress.ip_network('192.168.0.16/28')
>>> b_ip.subnet_of(a_ip)
True
>>> a_ip.subnet_of(b_ip)
False

IPアドレスをintにして計算

手順

  1. ipアドレス型に変換し、netowork_addressを取得する
  2. 1のipをint型に変換する
  3. ipアドレス型に変換し、broadcast_addressを取得する
  4. 3ののipをint型に変換する
  5. 24でintに変換したipをlistに格納する
  6. 比較したいipにも1-5の動作を行う
  7. 2つのlistを比較しipのsubnetを確認する
>>> a_int = [int(ipaddress.ip_network('192.168.0.0/24').network_address),int(ipaddress.ip_network('192.168.0.0/24').broadcast_address)]
>>> a_int
[3232235520, 3232235775]
>>> b_int = [int(ipaddress.ip_network('192.168.0.16/28').network_address),int(ipaddress.ip_network('192.168.0.16/28').broadcast_address)]
>>> b_int
[3232235536, 3232235551]
>>> c_int = [int(ipaddress.ip_network('192.168.0.0/16').network_address),int(ipaddress.ip_network('192.168.0.0/16').broadcast_address)]
>>> c_int
[3232235520, 3232301055]
>>> a_int[0] <= b_int[0] and b_int[1] <= a_int[1] # a="192.168.0.0/24" b="192.168.0.16/28"
True
>>> c_int[0] <= a_int[0] and a_int[1] <= c_int[1] # a="192.168.0.0/24" c="192.168.0.0/16"
True
>>> b_int[0] <= a_int[0] and a_int[1] <= b_int[1]
False
>>> a_int[0] <= c_int[0] and c_int[1] <= a_int[1]
False

ポイント

  • int型にすると処理が早い
    • 約2.26倍で処理している!!

    • int型にすると8.11 µs

      >>> %%time
      >>> a_int[0] <= b_int[0] and b_int[1] <= a_int[1]
      CPU times: user 5 µs, sys: 1 µs, total: 6 µs
      Wall time: 8.11 µs
      
    • ipアドレスで実行すると18.4µs

      >>> %%time
      >>> b_ip.subnet_of(a_ip)
      CPU times: user 14 µs, sys: 1e+03 ns, total: 15 µs
      Wall time: 18.4 µs
      

内包しているipの確認

  • イテレーション
    >>> for addr in ipaddress.IPv4Network('192.0.2.0/28'):
          print(addr)
    192.0.2.0
    192.0.2.1
    192.0.2.2
    192.0.2.3
    192.0.2.4
    192.0.2.5
    192.0.2.6
    192.0.2.7
    192.0.2.8
    192.0.2.9
    192.0.2.10
    192.0.2.11
    192.0.2.12
    192.0.2.13
    192.0.2.14
    192.0.2.15
    

参考

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2