python で ip address がネットワークに含まれるか計算したい
このIP 209.85.220.73 この、ネットワーク 209.85.128.0/17 に入るんだっけ。
計算してみる( ipaddress ) :2026/02/16 追記
python3.3 以降で 標準添付の import ipaddress を使うと楽です
import ipaddress # ネットワークオブジェクトの作成 net = ipaddress.ip_network("209.85.128.0/17") # IPアドレスオブジェクトの作成 ip = ipaddress.ip_address("209.85.220.73") # 判定(in 演算子が使える!) print(ip in net) # => True # ネットワークアドレスの確認 print(net.network_address) # => 209.85.128.0
計算してみる( netaddrを使う )
python の netaddr パッケージを用いて計算する
pip install netaddr ##または pipenv 経由で pipenv run pip install netaddr
要は、ふたつのIPのネットワークアドレスが一致すればいいわけですからこうすればいい。
from netaddr import * a = IPNetwork("209.85.220.73/17") a.network # => IPAddress('209.85.128.0') b = IPNetwork("209.85.128.0/17") b.network # => IPAddress('209.85.128.0') a.network == b.network
ショートカットに
これ、もうワンライナーで動きそうですね。
python3 -c "import sys;from netaddr import *; \ print( \ IPNetwork(sys.argv[1]).network == IPNetwork(sys.argv[2]).network) \ " 209.85.220.73/17 209.85.128.0/17
だったら alias でいけるか。
alias in_subnet='python3 -c "import sys;from netaddr import *; \ print(IPNetwork(sys.argv[1]).network == IPNetwork(sys.argv[2]).network)" ' in_subnet 209.85.220.73/17 209.85.128.0/17
2026-02-16 追記 ワンライナー( ipaddress 版)も考えてみる
alias in_subnet='python3 -c "import sys, ipaddress; \ print(ipaddress.ip_address(sys.argv[1]) in ipaddress.ip_network(sys.argv[2], strict=False))"' in_subnet 209.85.220.73 209.85.128.0/17
私としては netaddr のほうがオブジェクト指向に沿ってるので、好きだけど、pip インストールが必要なので面倒だったのが解消された
サブネットの計算は暗算できたほうが嬉しい
サブネットが一致するかの計算って、だいたいパターンなので暗算できるんだけど。
たとえば次のようにする。
209.85.220.73/17 を計算するに、
209.85.220.73/17 → 16+1 209.85.0.0/16 + 220/1 + 0 209.85.0.0/16 + 128 + 0 209.85.0.0/16 + 0.0.128.0 + 0.0.0.0 だから 209.85.220.73/17 → 209.85.128.0/17
範囲もそこから想像がつく
209.85.128.0/17 → 209.85.128.0 ~ 209.85.255.255
なので、209.85.220.73は範囲に含まれる。
これは、つぎの表を丸暗記しておけば、サクッと計算できるわけで。
| マスク | 1オクテット | 2オクテット | 3 オクテット | 4オクテット |
|---|---|---|---|---|
| /32 | 255 | 255 | 255 | 255 |
| /24 | 255 | 255 | 255 | 0 |
| /16 | 255 | 255 | 0 | 0 |
| /8 | 255 | 0 | 0 | 0 |
この表は、次のようになるわけで
| マスク | 1オクテット | 2オクテット | 3 オクテット | 4オクテット |
|---|---|---|---|---|
| /32 | 8 | 8 | 8 | 8 |
| /24 | 8 | 8 | 8 | 0 |
| /16 | 8 | 8 | 0 | 0 |
| /8 | 8 | 0 | 0 | 0 |
IPアドレスの1オクテット(8ビット)は次のように計算されるわけで
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
|---|---|---|---|---|---|---|---|
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| 128 | 64 | 32 | 16 | 8 | 4 | 2 | 1 |
オクテットを見ると、ビット数範囲が分かるわけで
| マスク | 1オクテット | 2オクテット | 3 オクテット | 4オクテット |
|---|---|---|---|---|
| /17 | 8 | 8 | 1 | 0 |
| /18 | 8 | 8 | 2 | 0 |
| /19 | 8 | 8 | 3 | 0 |
| マスク | 1オクテット | 2オクテット | 3 オクテット | 4オクテット |
|---|---|---|---|---|
| /17(16+1) | 8 | 8 | 1 | 0 |
| /18(16+2) | 8 | 8 | 2 | 0 |
| /19(16+3) | 8 | 8 | 3 | 0 |
| マスク | 数値 | 範囲 |
|---|---|---|
| /17(16+1) | 8 | 8 | 1 →(0-127,128-255) | 0 |
| /18(16+2) | 8 | 8 | 2 →(0-63,64-127,128-191,192-256)| 0 |
| /19(16+3) | 8 | 8 | 3 | 0 |
これを覚えておけば、だいたい計算できるわ
| マスク | 数値(分割数) | 範囲 | 数値 |
|---|---|---|---|
| 16+0 | 0 | (0-255) | 255 |
| 16+1 | 1 | (0-127,128-255) | 128 |
| 16+2 | 2 | (0-63,64-127,128-191,192-255) | 64 |
| 16+3 | 3 | (0-31,32-63,...,224-255) | 32 |
たとえば、/26の場合
26=24+2 なので、24 までの /255.255.255.0 までは変換しないとわかる。残りの2相当つまり、 0.0.0.64 の足し算だとわかる。
たとえば、 /17 の場合
17 の場合は、16+1 なので、16までの /255.255.0.0 は変換しないとわかる。残りの1相当つまり、 128 が以降がネットワークアドレスとわかる。
209.85.128.0/17 の場合
209.85.128.0/17 → 209.85.128.0/16+1 → 209.85.0.0/16 + 0.0.128.0 → 209.85.128.0
209.85.220.73/17の場合
209.85.220.73/17 → 209.85.220.73/(16+1) → 209.85.0.0/16 + 0.0.220.73/17 → 209.85.0.0/16 + 0.0.128.0 → 209.85.128.0
はたして、暗算での判断と、計算機を用いた場合のどちらが速いんだろう。
2026-02-16 更新
python3.3 の ipaddress に付いて言及