Comment utiliser python pour convertir une adresse IP sous la forme d'une str
en un nombre décimal et vice versa?
Par exemple, pour l'IP 186.99.109.000 <type'str'>
, j'aimerais une forme décimale ou binaire facile à stocker dans une base de données, puis à récupérer.
convertir une chaîne IP en entier long:
import socket, struct
def ip2long(ip):
"""
Convert an IP string to long
"""
packedIP = socket.inet_aton(ip)
return struct.unpack("!L", packedIP)[0]
l'inverse:
>>> socket.inet_ntoa(struct.pack('!L', 2130706433))
'127.0.0.1'
Voici un résumé de toutes les options à compter de 2017-06. Tous les modules font partie de la bibliothèque standard ou peuvent être installés via pip install
.
Le module ipaddress ( doc ) fait partie de la bibliothèque standard depuis la v3.3 mais il est également disponible en tant que module externe pour python v2.6, v2.7.
>>> import ipaddress
>>> int(ipaddress.ip_address('1.2.3.4'))
16909060
>>> ipaddress.ip_address(16909060).__str__()
'1.2.3.4'
>>> int(ipaddress.ip_address(u'1000:2000:3000:4000:5000:6000:7000:8000'))
21268296984521553528558659310639415296L
>>> ipaddress.ip_address(21268296984521553528558659310639415296L).__str__()
u'1000:2000:3000:4000:5000:6000:7000:8000'
Rien à importer, mais ne fonctionne que pour IPv4 et le code est plus long que toute autre option.
>>> ipstr = '1.2.3.4'
>>> parts = ipstr.split('.')
>>> (int(parts[0]) << 24) + (int(parts[1]) << 16) + \
(int(parts[2]) << 8) + int(parts[3])
16909060
>>> ipint = 16909060
>>> '.'.join([str(ipint >> (i << 3) & 0xFF)
for i in range(4)[::-1]])
'1.2.3.4'
netaddr est un module externe mais très stable et disponible depuis Python 2.5 ( doc )
>>> import netaddr
>>> int(netaddr.IPAddress('1.2.3.4'))
16909060
>>> str(netaddr.IPAddress(16909060))
'1.2.3.4'
>>> int(netaddr.IPAddress(u'1000:2000:3000:4000:5000:6000:7000:8000'))
21268296984521553528558659310639415296L
>>> str(netaddr.IPAddress(21268296984521553528558659310639415296L))
'1000:2000:3000:4000:5000:6000:7000:8000'
Les deux modules font partie de la bibliothèque standard, le code est court, un bit cryptique et IPv4 uniquement.
>>> import socket, struct
>>> ipstr = '1.2.3.4'
>>> struct.unpack("!L", socket.inet_aton(ipstr))[0]
16909060
>>> ipint=16909060
>>> socket.inet_ntoa(struct.pack('!L', ipint))
'1.2.3.4'
Utilisez la classe IPAddress
dans le module netaddr
.
ipv4 str
-> int
:
print int(netaddr.IPAddress('192.168.4.54'))
# OUTPUT: 3232236598
ipv4 int
-> str
:
print str(netaddr.IPAddress(3232236598))
# OUTPUT: 192.168.4.54
ipv6 str
-> int
:
print int(netaddr.IPAddress('2001:0db8:0000:0000:0000:ff00:0042:8329'))
# OUTPUT: 42540766411282592856904265327123268393
ipv6 int
-> str
:
print str(netaddr.IPAddress(42540766411282592856904265327123268393))
# OUTPUT: 2001:db8::ff00:42:8329
Depuis Python 3.3, il existe un module ipaddress qui fait exactement ce travail entre autres: https://docs.python.org/3/library/ipaddress.html . Les backports pour Python 2.x sont également disponibles sur PyPI.
Exemple d'utilisation:
import ipaddress
ip_in_int = int(ipaddress.ip_address('192.168.1.1'))
ip_in_hex = hex(ipaddress.ip_address('192.168.1.1'))
import socket, struct
def ip2long_1(ip):
return struct.unpack("!L", socket.inet_aton(ip))[0]
def ip2long_2(ip):
return long("".join(["{0:08b}".format(int(num)) for num in ip.split('.')]), 2)
def ip2long_3(ip):
return long("".join(["{0:08b}".format(num) for num in map(int, ip.split('.'))]), 2)
ip2long_1 => 0.0527065660363234 (Le meilleur)
ip2long_2 => 0.577211893924598
ip2long_3 => 0.5552745958088666
Solution à une ligne sans aucune importation de module:
ip2int = lambda ip: reduce(lambda a, b: (a << 8) + b, map(int, ip.split('.')), 0)
int2ip = lambda n: '.'.join([str(n >> (i << 3) & 0xFF) for i in range(0, 4)[::-1]])
Exemple:
In [3]: ip2int('121.248.220.85')
Out[3]: 2046352469
In [4]: int2ip(2046352469)
Out[4]: '121.248.220.85'
Convertir l'IP en entier:
python -c "print sum( [int(i)*2**(8*j) for i,j in Zip( '10.20.30.40'.split('.'), [3,2,1,0]) ] )"
Convertir un entier en IP:
python -c "print '.'.join( [ str((169090600 >> 8*i) % 256) for i in [3,2,1,0] ])"
def ip2Hex(ip = None):
'''Returns IP in Int format from Octet form'''
#verifyFormat(ip)
digits=ip.split('.')
numericIp=0
count=0
for num in reversed(digits):
print "%d " % int(num)
numericIp += int(num) * 256 **(count)
count +=1
print "Numeric IP:",numericIp
print "Numeric IP Hex:",hex(numericIp)
ip2Hex('192.168.192.14')
ip2Hex('1.1.1.1')
ip2Hex('1.0.0.0')
En voici un
def ipv4_to_int(ip):
octets = ip.split('.')
count = 0
for i, octet in enumerate(octets):
count += int(octet) << 8*(len(octets)-(i+1))
return count