Подтвердить что ты не робот

Преобразуйте строку IP в число и наоборот

Как я могу использовать python для преобразования IP-адреса, который приходит как str в десятичное число и наоборот?

Например, для IP 186.99.109.000 <type'str'> я хотел бы иметь десятичную или двоичную форму, которую легко хранить в базе данных, а затем извлекать ее.

4b9b3361

Ответ 1

преобразование строки IP в длинное целое:

import socket, struct

def ip2long(ip):
    """
    Convert an IP string to long
    """
    packedIP = socket.inet_aton(ip)
    return struct.unpack("!L", packedIP)[0]

наоборот:

>>> socket.inet_ntoa(struct.pack('!L', 2130706433))
'127.0.0.1'

Ответ 2

Использовать класс IPAddress в модуле netaddr.

ipv4 strint:

print int(netaddr.IPAddress('192.168.4.54'))
# OUTPUT: 3232236598

ipv4 intstr:

print str(netaddr.IPAddress(3232236598))
# OUTPUT: 192.168.4.54

ipv6 strint:

print int(netaddr.IPAddress('2001:0db8:0000:0000:0000:ff00:0042:8329'))
# OUTPUT: 42540766411282592856904265327123268393

ipv6 intstr:

print str(netaddr.IPAddress(42540766411282592856904265327123268393))
# OUTPUT: 2001:db8::ff00:42:8329

Ответ 3

Вот сводка всех вариантов с 2017-06. Все модули являются частью стандартной библиотеки или могут быть установлены через pip install.

модуль ipaddress

Модуль ipaddress (doc) является частью стандартной библиотеки с версии 3, но также доступен как внешний модуль для python v2 0,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'

Импорт модуля (только для IPv4)

Ничего не импортировать, но работает только для IPv4, а код длиннее любого другого.

>>> 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

netaddr - это внешний модуль, но он очень стабилен и доступен с 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'

Модули socket и struct (только для ipv4)

Оба модуля являются частью стандартной библиотеки, код короток, немного критический и только IPv4.

>>> 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'

Ответ 4

Так как Python 3.3 есть модуль ipaddress, который выполняет именно эту работу среди других: https://docs.python.org/3/library/ipaddress.html. Backports для Python 2.x также доступны в PyPI.

Пример использования:

import ipaddress

ip_in_int = int(ipaddress.ip_address('192.168.1.1'))
ip_in_hex = hex(ipaddress.ip_address('192.168.1.1'))

Ответ 5

Здесь ответы на одну линию:

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 (лучший)
ip2long_2 = > 0.577211893924598
ip2long_3 = > 0.5552745958088666

Ответ 6

Однострочное решение без импорта модуля:

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]])

Пример:

In [3]: ip2int('121.248.220.85')
Out[3]: 2046352469

In [4]: int2ip(2046352469)
Out[4]: '121.248.220.85'

Ответ 7

Преобразование IP в целое число:

python -c "print sum( [int(i)*2**(8*j) for  i,j in zip( '10.20.30.40'.split('.'), [3,2,1,0]) ] )"

Преобразование Interger в IP:

python -c "print '.'.join( [ str((169090600 >> 8*i) % 256)  for i in [3,2,1,0] ])" 

Ответ 8

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')

Ответ 9

@ndemou

Вот простой тестовый тест для большинства примеров в ответе @ndemou. Если вы уже используете модуль ipaddress для своих адресов, IP int предварительно вычисляется, поэтому это самый быстрый метод. В противном случае socket/struct является самым быстрым методом довольно много.

https://ideone.com/cZU9Ar

PS: Я бы добавил это в качестве комментария, но у меня недостаточно очков.