What's the best way to turn a string in this form into an IP address: "0200A8C0"
. The "octets" present in the string are in reverse order, i.e. the given example string should generate 192.168.0.2
.
Network address manipulation is provided by the socket module.
Convert a 32-bit packed IPv4 address (a string four characters in length) to its standard dotted-quad string representation (for example, ‘123.45.67.89’). This is useful when conversing with a program that uses the standard C library and needs objects of type struct in_addr, which is the C type for the 32-bit packed binary data this function takes as an argument.
You can translate your hex string to packed ip
using struct.pack()
and the little endian, unsigned long format.
s = "0200A8C0"
import socket
import struct
addr_long = int(s, 16)
print(hex(addr_long)) # '0x200a8c0'
print(struct.pack("<L", addr_long)) # '\xc0\xa8\x00\x02'
print(socket.inet_ntoa(struct.pack("<L", addr_long))) # '192.168.0.2'
192.168.10.5
hex is c0a80a05
. When I use this snippet to convert from HEX to IP, I get 5.10.168.192
. Which is correct but reversed. To make it work I have to change <L
to >L
which doesn't make any sense if I take the input from a user and I don't know what HEX is the input! Do you have any idea how to make it work for any HEX value? Thank you –
Hanna >>> s = "0200A8C0"
>>> bytes = ["".join(x) for x in zip(*[iter(s)]*2)]
>>> bytes
['02', '00', 'A8', 'C0']
>>> bytes = [int(x, 16) for x in bytes]
>>> bytes
[2, 0, 168, 192]
>>> print ".".join(str(x) for x in reversed(bytes))
192.168.0.2
It is short and clear; wrap it up in a function with error checking to suit your needs.
Handy grouping functions:
def group(iterable, n=2, missing=None, longest=True):
"""Group from a single iterable into groups of n.
Derived from http://bugs.python.org/issue1643
"""
if n < 1:
raise ValueError("invalid n")
args = (iter(iterable),) * n
if longest:
return itertools.izip_longest(*args, fillvalue=missing)
else:
return itertools.izip(*args)
def group_some(iterable, n=2):
"""Group from a single iterable into groups of at most n."""
if n < 1:
raise ValueError("invalid n")
iterable = iter(iterable)
while True:
L = list(itertools.islice(iterable, n))
if L:
yield L
else:
break
zip(*[iter(s)]*2)
work? I'm very interested in that. –
Ruben iter(s)
returns an iterator over the string. Multiplying the list of this iterator by 2 will create two references to the same iterator. zip()
returns a list of tuples containing an element from each of its arguments. Since both arguments are the same iterator, it will take from it twice for each tuple, returning a tuple of each 2 adjacent characters. I would never have thought of trying anything like this. :D –
Pantomime You could do something like this:
>>> s = '0200A8C0'
>>> octets = [s[i:i+2] for i in range(0, len(s), 2)]
>>> ip = [int(i, 16) for i in reversed(octets)]
>>> ip_formatted = '.'.join(str(i) for i in ip)
>>> print ip_formatted
192.168.0.2
The octet splitting could probably be done more elegantly, but I can't think of a simpler way off the top of my head.
EDIT: Or on one line:
>>> s = '0200A8C0'
>>> print '.'.join(str(int(i, 16)) for i in reversed([s[i:i+2] for i in range(0, len(s), 2)]))
192.168.0.2
My try:
a = '0200A8C0'
indices = range(0, 8, 2)
data = [str(int(a[x:x+2], 16)) for x in indices]
'.'.join(reversed(data))
In "modern" Python I do it like this (short, simple, pythonic, concise, clear and no additional imports requires)
hex_address = '0200A8C0' # 4 bytes in little-endian notation
ip_address = '.'.join(map(str, reversed(bytearray.fromhex(hex_address))))
print(ip_address) # prints '192.168.0.2'
Steps
- the
builtin
bytearray.fromhex method converts the4 bytes hexidecimal
address string to a iterable of4 integers
- the iteration direction is
reversed
before joining becausehex_address
is in little-endian notation (the least-significant byte at the smallest address) - integers are converted to a
str
so they can be joined with the.
character
A simple def you can make to convert from hex to decimal-ip:
def hex2ip(iphex):
ip = ["".join(x) for x in zip(*[iter(str(iphex))]*2)]
ip = [int(x, 16) for x in ip]
ip = ".".join(str(x) for x in (ip))
return ip
# And to use it:
ip = "ac10fc40"
ip = hex2ip(iphex)
print(ip)
© 2022 - 2025 — McMap. All rights reserved.
pack
, though "<L" will work too. Otherwise you're leaving yourself open to whatever the platform endianess is. – Kohima