ich habe ein kleines Problem mit meinem Skript, bei dem ich IP in der Form 'xxx.xxx.xxx.xxx' in eine Ganzzahldarstellung konvertieren und von dieser Form zurückgehen muss.
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`
Weiß jemand, wie man das repariert?
#!/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
Python 3 verfügt über das Modul ipaddress , das eine sehr einfache Konvertierung bietet:
int(ipaddress.IPv4Address("192.168.0.1"))
str(ipaddress.IPv4Address(3232235521))
In reinem Python ohne Zusatzmodul
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))
Ergebnis:
192.168.0.1 -> 3232235521
3232235521 -> 192.168.0.1
Sie verlieren das Left-Zero-Padding, wodurch die Dekodierung Ihrer Zeichenfolge unterbrochen wird.
Hier ist eine Arbeitsfunktion:
def inttoip(ip):
return socket.inet_ntoa(hex(ip)[2:].zfill(8).decode('hex'))
Nachfolgend sind die schnellsten und unkompliziertesten (nach meinem besten Wissen) Konverter für IPv4 und IPv6 aufgeführt:
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))
Python-Code, der das inet_ntop()
- und struct
-Modul nicht verwendet, ist um eine Größenordnung langsamer als diese, unabhängig davon, was er tut.
Eine Linie
reduce(lambda out, x: (out << 8) + int(x), '127.0.0.1'.split('.'), 0)
Mein Ansatz ist es, die Zahl, in der sie gespeichert ist, direkt anzuzeigen, anstatt sie anzuzeigen, und sie vom Anzeigeformat in das gespeicherte Format und umgekehrt zu manipulieren.
Also von einer IP-Adresse zu einem int:
def convertIpToInt(ip):
return sum([int(ipField) << 8*index for index, ipField in enumerate(reversed(ip.split('.')))])
Dadurch wird jedes Feld ausgewertet und auf den korrekten Offset verschoben. Dann werden alle Felder zusammengefasst und die Anzeige der IP-Adresse wird in den numerischen Wert umgewandelt.
In umgekehrter Richtung von einem int zu einer IP-Adresse:
def convertIntToIp(ipInt):
return '.'.join([str(int(ipHexField, 16)) for ipHexField in (map(''.join, Zip(*[iter(str(hex(ipInt))[2:].zfill(8))]*2)))])
Die numerische Darstellung wird zuerst in ihre hexadezimale Zeichenfolgendarstellung konvertiert, die als Sequenz geändert werden kann, um das Auflösen zu erleichtern. Dann werden Paare extrahiert, indem '' .join 'auf Tupel von Paaren abgebildet wird, die bereitgestellt werden, indem eine Liste von zwei Referenzen zu einem Iterator des IP-Strings gezippt wird (siehe Wie funktioniert Zip (* [iter (s)] * n)? ), und diese Paare werden wiederum von Hex-String-Darstellungen in Int-String-Darstellungen konvertiert und durch '.' verbunden.
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'
Lassen Sie mich einen verständlicheren Weg geben:
ip zu 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
Obenstehendes:
lst = [int(item) for item in s_ip.split('.')]
gleichwertig :
lst = map(int, s_ip.split('.'))
ebenfalls:
int_ip = lst[3] | lst[2] << 8 | lst[1] << 16 | lst[0] << 24
gleichwertig :
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 zu 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])
oder:
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)