将“小端”十六进制字符串转换为Python中的IP地址

11 投票
6 回答
28590 浏览
提问于 2025-04-15 18:52

怎么把这样的字符串转换成IP地址呢:"0200A8C0"。这个字符串里的“八位组”顺序是反的,也就是说,给出的这个例子字符串应该生成192.168.0.2

6 个回答

3

你可以这样做:

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

把八位字节分开可能还有更优雅的方法,但我一时想不出更简单的。

补充:或者可以用一行代码来实现:

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

这个代码简洁明了;把它放进一个函数里,并加上错误检查,按照你的需求来调整。


实用的分组函数:

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
35

网络地址的处理是通过socket模块来实现的。

socket.inet_ntoa(packed_ip)

这个函数可以把一个32位的打包IPv4地址(长度为四个字符的字符串)转换成标准的点分十进制字符串表示(比如‘123.45.67.89’)。这在和使用标准C库的程序进行交流时很有用,因为这些程序需要一种叫做struct in_addr的对象,这种对象是C语言中用于表示32位打包二进制数据的类型,而这个函数就是用来处理这种数据的。

你可以使用struct.pack()函数和小端格式的无符号长整型,把你的十六进制字符串转换成packed ip

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'

撰写回答