Python 网络编程小技巧(一)——获取本机 MAC 地址

本篇博文介绍如何利用 Python 的 uuid 标准库获取本机 MAC 地址。

利用 Python 获取本机 MAC 地址非常简便,使用 uuid 标准库之后,一行代码即可获取,这里先展示出来,之后对这行代码进行分析:

print(":".join([uuid.uuid1().hex[-12:][i : i + 2] for i in range(0, 11, 2)]))

我们运行一下这句代码,发现确实打印出了本机的 MAC 地址:
在这里插入图片描述
然后,我们来观察一下这句代码,发现它的核心代码是:

uuid.uuid1().hex[-12:]

这个代码是什么意思呢?我们打印它一下看看:

发现相对于刚才的结果,它的数字之间没有了冒号,这说明刚才的代码除了核心代码都是在做格式的相应处理,因此我们只需把目光关注在核心代码上,那么这句核心代码是干什么呢?

首先,我们要来了解一个库 uuid,uuid 是 Python 的标准库,代表的是通用唯一识别码(Universally Unique Identifier)的缩写,字面意思就是生成一个对任何东西都可以进行唯一识别的编码,它在多个领域都有应用。

uuid 有多个生成 UUID 的函数,其中 uuid1() 函数从 MAC 地址、序列号和当前时间生成 UUID,通过该函数生成的 UUID 的最后 12 个字符就是本机的 MAC 地址,因此可能会暴露 MAC 地址从而损害隐私。

为了深入一点了解,我们来分别打印:

uuid.uuid1()
uuid.uuid1().hex

可以看到它们分别其实没有太大区别,都包含本机 MAC 地址 a4:7e:5d:a3:a2:d4,不过 uuid.uuid1() 生成的是一个 uuid.UUID 的类对象,而 uuid.uuid1().hex 是该类对象的内容的十六进制表现形式,之前代码中的 [-12:] 就代表取最后 12 位(注意,最后 12 位前面的众多位数是根据序列号和当前时间生成的):
在这里插入图片描述
所以也可以使用以下代码将 uuid.UUID 类对象转换为字符串来获取本机 MAC 地址:

print(":".join([str(uuid.uuid1())[-12:][i : i + 2] for i in range(0, 11, 2)]))

刚才也说了,uuid.uuid1() 生成的是一个 uuid.UUID 的类对象,那么不由得就产生一个疑问,这个类对象怎么就可以获得本机 MAC 地址呢?难道是这个函数它自己获取到 MAC 地址,然后封装到对象里面了吗?带着这个疑问,我们可以看一下这个函数的源码,然而,当我们链入这个函数时,我们就可以发现答案已经给出来了:
在这里插入图片描述
uuid1() 函数的注释上明确说明,当 node 没有给定时,它会使用 getnode() 函数,然后,这个 getnode() 函数就可以获取本机的硬件地址也就是我们的 MAC 地址,那么我们接下来就可以直接去找这个 getnode() 函数就好了,这里给出它对应的源码,然后我们进行分析:

_node = None

_NODE_GETTERS_WIN32 = [_windll_getnode, _netbios_getnode, _ipconfig_getnode]

_NODE_GETTERS_UNIX = [_unix_getnode, _ifconfig_getnode, _ip_getnode,
                      _arp_getnode, _lanscan_getnode, _netstat_getnode]

def getnode(*, getters=None):
    """Get the hardware address as a 48-bit positive integer.

    The first time this runs, it may launch a separate program, which could
    be quite slow.  If all attempts to obtain the hardware address fail, we
    choose a random 48-bit number with its eighth bit set to 1 as recommended
    in RFC 4122.
    """
    global _node
    if _node is not None:
        return _node

    if sys.platform == 'win32':
        getters = _NODE_GETTERS_WIN32
    else:
        getters = _NODE_GETTERS_UNIX

    for getter in getters + [_random_getnode]:
        try:
            _node = getter()
        except:
            continue
        if (_node is not None) and (0 <= _node < (1 << 48)):
            return _node
    assert False, '_random_getnode() returned invalid value: {}'.format(_node)

观察该函数的注释,我们发现 getnode() 函数可以将 48 位的硬件地址转换成十进制正整数形式返回给我们,我们不妨测试一下,我们运行下面这句代码:

print(uuid.getnode())

可以看到打印出的一串十进制数:
在这里插入图片描述
我们验证一下,发现 180862643839700 确实是 MAC 地址 a4:7e:5d:a3:a2:d4 的十进制形式:
在这里插入图片描述
因此,我们又可以用一种形式去获得本机 MAC 地址:

print(":".join([hex(uuid.getnode())[-12:][i : i + 2] for i in range(0, 11, 2)]))

最后,总结一下,我们可以有以下几种简便的方式来获取本机 MAC 地址:

print(":".join([uuid.uuid1().hex[-12:][i : i + 2] for i in range(0, 11, 2)]))
print(":".join([str(uuid.uuid1())[-12:][i : i + 2] for i in range(0, 11, 2)]))
print(":".join([hex(uuid.getnode())[-12:][i : i + 2] for i in range(0, 11, 2)]))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值