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
.

- 112,946
- 110
- 377
- 526
5 Answers
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'
-
1You want " – Omnifarious Feb 04 '10 at 07:50
-
@Omnifarious, how exactly does it's "long/int"ness effect it here? – Matt Joiner Feb 04 '10 at 07:57
-
`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` 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 – Tes3awy Apr 14 '21 at 00:59
>>> 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
-
@Roger, how does that `zip(*[iter(s)]*2)` work? I'm very interested in that. – Matt Joiner Feb 04 '10 at 07:54
-
4This is quite the hack! `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 – Max Shawabkeh Feb 04 '10 at 08:24
-
@Matt: It's the core of most "grouping" recipes I've seen, and Max explained it well. Will update to include two short functions in that vein. – Feb 04 '10 at 11:12
-
@Roger, thanks very much, I was hoping a solution like yours would come up. – Matt Joiner Feb 04 '10 at 17:26
-
I've created a new question, which directly asks what you've solved here: http://stackoverflow.com/questions/2202461/yield-multiple-objects-at-a-time-from-an-iterable-object – Matt Joiner Feb 04 '10 at 19:13
-
+1 That zip iter trick is mindbogglingly useful for code golf. Awesome. – Exelian Sep 01 '11 at 14:49
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

- 37,799
- 10
- 82
- 91
-
yeah teh grouping in particular gets to me. i can't find a nice way to "chunk" the octets out, and iterate _those_ in reverse order, i'm hoping someone knows a way – Matt Joiner Feb 04 '10 at 07:43
-
My try:
a = '0200A8C0'
indices = range(0, 8, 2)
data = [str(int(a[x:x+2], 16)) for x in indices]
'.'.join(reversed(data))

- 93,253
- 21
- 125
- 158
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)

- 55
- 7