我需要一种跨平台的方法来在运行时确定计算机的MAC地址。对于Windows系统可以使用'wmi'模块,而在Linux系统下我只能找到运行ifconfig并在其输出上运行正则表达式的方法。我不喜欢使用只适用于一个操作系统的软件包,并且解析另一个程序的输出似乎并不优雅,更不用说容易出错了。
有人知道一种跨平台的方法(适用于Windows和Linux系统)来获取MAC地址吗?如果没有,是否有任何比我上面列出的方法更优雅的方法呢?
我需要一种跨平台的方法来在运行时确定计算机的MAC地址。对于Windows系统可以使用'wmi'模块,而在Linux系统下我只能找到运行ifconfig并在其输出上运行正则表达式的方法。我不喜欢使用只适用于一个操作系统的软件包,并且解析另一个程序的输出似乎并不优雅,更不用说容易出错了。
有人知道一种跨平台的方法(适用于Windows和Linux系统)来获取MAC地址吗?如果没有,是否有任何比我上面列出的方法更优雅的方法呢?
Python 2.5 包含一个 uuid 实现,但至少有一个版本需要 mac 地址。你可以轻松地将查找 mac 地址的函数导入到自己的代码中:
from uuid import getnode as get_mac
mac = get_mac()
返回值是MAC地址的48位整数。
getnode
文档,它表示如果无法检测到 MAC 地址,它将返回一个随机的长整形数:"如果所有获取硬件地址的尝试都失败了,我们选择一个随机的 48 位数,并将其第八个比特设置为 1,正如 RFC 4122 建议的那样。" 因此请检查第八个比特! - deinonychusaurhex(mac)
可以获得MAC地址的熟悉十六进制格式。 - screenshot345':'.join(("%012X" % mac)[i:i+2] for i in range(0, 12, 2))
。 - tomlogic这个问题在Linux下获取特定本地接口的MAC地址的纯Python解决方案,最初是由vishnubob在Ben Mackey的此Activestate recipe中作为评论发布的,并得到改进。
#!/usr/bin/python
import fcntl, socket, struct
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', ifname[:15]))
return ':'.join(['%02x' % ord(char) for char in info[18:24]])
print getHwAddr('eth0')
以下是兼容Python 3的代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import fcntl
import socket
import struct
def getHwAddr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15]))
return ':'.join('%02x' % b for b in info[18:24])
def main():
print(getHwAddr('enp0s8'))
if __name__ == "__main__":
main()
netifaces
是一个很好的模块,用于获取MAC地址(和其他地址)。它是跨平台的,比使用socket或uuid更加合理。
import netifaces
netifaces.interfaces()
# ['lo', 'eth0', 'tun2']
netifaces.ifaddresses('eth0')[netifaces.AF_LINK]
# [{'addr': '08:00:27:50:f2:51', 'broadcast': 'ff:ff:ff:ff:ff:ff'}]
有时我们会有多个网络接口。
找出特定接口的MAC地址的简单方法是:
def getmac(interface):
try:
mac = open('/sys/class/net/'+interface+'/address').readline()
except:
mac = "00:00:00:00:00:00"
return mac[0:17]
调用该方法很简单
myMAC = getmac("wlan0")
return mac.strip()
可能更容易去掉换行符 ;-) - Pedro A. Aranda需要注意的一点是uuid.getnode()
函数可以通过返回一个随机的48位数字来伪造MAC地址,这可能不是你所期望的结果。此外,并没有明确指示MAC地址已被伪造,但您可以通过调用两次getnode()
并查看结果是否变化来检测它。如果两次调用都返回相同的值,则这就是真正的MAC地址,否则您将得到一个伪造地址。
>>> print uuid.getnode.__doc__
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.
使用我在这里的答案:https://stackoverflow.com/a/18031868/2362361
重要的是要知道你想获取哪个iface的MAC地址,因为可能存在许多(蓝牙、多个网络接口卡等)。
如果您知道需要获取MAC地址的iface的IP地址,则可以使用netifaces
(可在PyPI中获取)来完成此操作:
import netifaces as nif
def mac_for_ip(ip):
'Returns a list of MACs for interfaces that have given IP, returns None if not found'
for i in nif.interfaces():
addrs = nif.ifaddresses(i)
try:
if_mac = addrs[nif.AF_LINK][0]['addr']
if_ip = addrs[nif.AF_INET][0]['addr']
except IndexError, KeyError: #ignore ifaces that dont have MAC or IP
if_mac = if_ip = None
if if_ip == ip:
return if_mac
return None
测试:
>>> mac_for_ip('169.254.90.191')
'2c:41:38:0a:94:8b'
您可以使用跨平台的psutil来实现此操作:
import psutil
nics = psutil.net_if_addrs()
print [j.address for j in nics[i] for i in nics if i!="lo" and j.family==17]
import socket
then [addr.address for n in nics for addr in nics[n] if n == 'enp4s0' and addr.family == socket.AF_PACKET]
results in ['ab:cd:ef:01:02:03']
- Donn Leefrom getmac import get_mac_address
eth_mac = get_mac_address(interface="eth0")
win_mac = get_mac_address(interface="Ethernet 3")
ip_mac = get_mac_address(ip="192.168.0.1")
ip6_mac = get_mac_address(ip6="::1")
host_mac = get_mac_address(hostname="localhost")
updated_mac = get_mac_address(ip="10.0.0.1", network_request=True)
免责声明:我是该包的作者。
更新(2019年1月14日):该包现在仅支持Python 2.7+和3.4+。如果您需要使用旧版本的Python(2.5、2.6、3.2、3.3),您仍然可以使用旧版本的该包。
import platform
if platform.system() == 'Linux':
import LinuxMac
mac_address = LinuxMac.get_mac_address()
elif platform.system() == 'Windows':
# etc
要获取eth0
接口的MAC地址,
import psutil
nics = psutil.net_if_addrs()['eth0']
for interface in nics:
if interface.family == 17:
print(interface.address)