web-dev-qa-db-fra.com

Conversion de chaîne IP en entier et inversement en Python

j'ai un petit problème avec mon script, où j'ai besoin de convertir ip sous la forme 'xxx.xxx.xxx.xxx' en représentation entière et revenir de cette forme.

def iptoint(ip):
    return int(socket.inet_aton(ip).encode('hex'),16)

def inttoip(ip):
    return socket.inet_ntoa(hex(ip)[2:].decode('hex'))


In [65]: inttoip(iptoint('192.168.1.1'))
Out[65]: '192.168.1.1'

In [66]: inttoip(iptoint('4.1.75.131'))
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)

/home/thc/<ipython console> in <module>()

/home/thc/<ipython console> in inttoip(ip)

error: packed IP wrong length for inet_ntoa`

Quelqu'un sait comment résoudre ce problème?

38
thc_flow
#!/usr/bin/env python
import socket
import struct


def ip2int(addr):
    return struct.unpack("!I", socket.inet_aton(addr))[0]


def int2ip(addr):
    return socket.inet_ntoa(struct.pack("!I", addr))


print(int2ip(0xc0a80164)) # 192.168.1.100
print(ip2int('10.0.0.1')) # 167772161
74
fiorix

Python 3 a ipaddress module qui présente une conversion très simple:

int(ipaddress.IPv4Address("192.168.0.1"))
str(ipaddress.IPv4Address(3232235521))
27
markhor

En python pur sans utiliser de module supplémentaire

def IP2Int(ip):
    o = map(int, ip.split('.'))
    res = (16777216 * o[0]) + (65536 * o[1]) + (256 * o[2]) + o[3]
    return res


def Int2IP(ipnum):
    o1 = int(ipnum / 16777216) % 256
    o2 = int(ipnum / 65536) % 256
    o3 = int(ipnum / 256) % 256
    o4 = int(ipnum) % 256
    return '%(o1)s.%(o2)s.%(o3)s.%(o4)s' % locals()

# Example
print('192.168.0.1 -> %s' % IP2Int('192.168.0.1'))
print('3232235521 -> %s' % Int2IP(3232235521))

Résultat:

192.168.0.1 -> 3232235521
3232235521 -> 192.168.0.1
17
Bruno Adelé

Vous perdez le remplissage à zéro zéro qui interrompt le décodage de votre chaîne.

Voici une fonction de travail:

def inttoip(ip):
    return socket.inet_ntoa(hex(ip)[2:].zfill(8).decode('hex'))
12
ThiefMaster

Vous trouverez ci-dessous les convertisseurs les plus rapides et les plus simples (à ma connaissance) Pour IPv4 et IPv6:

    try:
        _str = socket.inet_pton(socket.AF_INET, val)
    except socket.error:
        raise ValueError
    return struct.unpack('!I', _str)[0]
    -------------------------------------------------
    return socket.inet_ntop(socket.AF_INET, struct.pack('!I', n))
    -------------------------------------------------
    try:
        _str = socket.inet_pton(socket.AF_INET6, val)
    except socket.error:
        raise ValueError
    a, b = struct.unpack('!2Q', _str)
    return (a << 64) | b
    -------------------------------------------------
    a = n >> 64
    b = n & ((1 << 64) - 1)
    return socket.inet_ntop(socket.AF_INET6, struct.pack('!2Q', a, b))

Le code Python n'utilisant pas les modules inet_ntop() et struct est comme un ordre de grandeur plus lent que cela indépendamment de ce qu'il fait.

6
adobriyan

Une ligne

reduce(lambda out, x: (out << 8) + int(x), '127.0.0.1'.split('.'), 0)
3
Thomas Webber

Mon approche consiste à regarder directement le nombre de la manière dont il est stocké, plutôt qu’à l’afficher, et à le manipuler du format d’affichage au format enregistré et vice-versa.

Donc, d'une adresse IP à un int:

def convertIpToInt(ip):
    return sum([int(ipField) << 8*index for index, ipField in enumerate(reversed(ip.split('.')))])

Ceci évalue chaque champ et le décale vers son offset correct, puis les additionne, convertissant avec précision l'affichage de l'adresse IP en valeur numérique.

Dans le sens opposé, d'un int à une adresse IP:

def convertIntToIp(ipInt):
    return '.'.join([str(int(ipHexField, 16)) for ipHexField in (map(''.join, Zip(*[iter(str(hex(ipInt))[2:].zfill(8))]*2)))])

La représentation numérique est d'abord convertie en sa représentation sous forme de chaîne hexadécimale, qui peut être manipulée sous forme de séquence, ce qui facilite sa fragmentation. Ensuite, les paires sont extraites en mappant '' .join sur des nuplets de paires fournis en zippant une liste de deux références à un itérateur de la chaîne IP (voir Comment fonctionne Zip (* [iteur (s)] * n)? ), et ces paires sont à leur tour converties de représentations de chaîne hexagonale en représentations de chaîne int, et jointes par '.'.

0
Gavi Teitz

J'ai utilisé le suivant:

ip2int = lambda ip: reduce(lambda a,b: long(a)*256 + long(b), ip.split('.'))

ip2int('192.168.1.1')

#output

3232235777L

# from int to ip
int2ip = lambda num: '.'.join( [ str((num >> 8*i) % 256)  for i in [3,2,1,0] ])

int2ip(3232235777L)

#output

'192.168.1.1'
0
J0KER11

Laissez-moi vous donner une façon plus compréhensible:

ip to int  

def str_ip2_int(s_ip='192.168.1.100'):
    lst = [int(item) for item in s_ip.split('.')]
    print lst   
    # [192, 168, 1, 100]

    int_ip = lst[3] | lst[2] << 8 | lst[1] << 16 | lst[0] << 24
    return int_ip   # 3232235876

Ce qui précède:

lst = [int(item) for item in s_ip.split('.')]

équivalent à :

lst = map(int, s_ip.split('.'))

également:

int_ip = lst[3] | lst[2] << 8 | lst[1] << 16 | lst[0] << 24

équivalent à :

int_ip = lst[3] + (lst[2] << 8) + (lst[1] << 16) + (lst[0] << 24)

int_ip = lst[3] + lst[2] * pow(2, 8) + lst[1] * pow(2, 16) + lst[0] * pow(2, 24)

int to ip:

def int_ip2str(int_ip=3232235876):
    a0 = str(int_ip & 0xff)
    a1 = str((int_ip & 0xff00) >> 8) 
    a2 = str((int_ip & 0xff0000) >> 16)
    a3 = str((int_ip & 0xff000000) >> 24)

    return ".".join([a3, a2, a1, a0])

ou:

def int_ip2str(int_ip=3232235876):
    lst = []
    for i in xrange(4):
        shift_n = 8 * i
        lst.insert(0, str((int_ip >> shift_n) & 0xff))

    return ".".join(lst)
0
Jayhello