Получение MAC-адреса - PullRequest
       60

Получение MAC-адреса

96 голосов
/ 01 октября 2008

Мне нужен кроссплатформенный метод определения MAC-адреса компьютера во время выполнения. Для windows можно использовать модуль 'wmi', и единственный метод под Linux, который я смог найти, это запустить ifconfig и запустить регулярное выражение через его вывод. Мне не нравится использовать пакет, который работает только на одной ОС, и анализ выходных данных другой программы выглядит не очень элегантно, не говоря уже о подверженности ошибкам.

Кто-нибудь знает метод кросс-платформенного метода (windows и linux) для получения MAC-адреса? Если нет, знает ли кто-нибудь более изящные методы, чем те, что я перечислил выше?

Ответы [ 13 ]

141 голосов
/ 01 октября 2008

Python 2.5 включает в себя реализацию uuid, которой (по крайней мере, в одной версии) нужен MAC-адрес Вы можете легко импортировать функцию поиска Mac в свой собственный код:

from uuid import getnode as get_mac
mac = get_mac()

Возвращаемым значением является MAC-адрес в виде 48-битного целого числа.

77 голосов
/ 25 января 2011

Чистое решение Python для этой проблемы под Linux, чтобы получить MAC для определенного локального интерфейса, первоначально опубликованный в качестве комментария vishnubob и улучшенный Беном Макки в этом рецепте activestate

#!/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()
26 голосов
/ 01 октября 2008

netifaces - хороший модуль для получения MAC-адреса (и других адресов). Он кроссплатформенный и имеет больше смысла, чем использование сокетов или 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'}]

20 голосов
/ 02 октября 2008

Еще одна вещь, на которую следует обратить внимание, это то, что uuid.getnode() может подделать MAC-адрес, возвращая случайное 48-битное число, которое может не соответствовать ожидаемому. Кроме того, нет явного указания на то, что 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.
16 голосов
/ 18 августа 2015

Иногда у нас более одного сетевого интерфейса.

Простой способ узнать 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")
8 голосов
/ 03 августа 2013

Используя мой ответ отсюда: https://stackoverflow.com/a/18031868/2362361

Было бы важно знать, для какого случая вам нужен MAC, поскольку многие могут существовать (Bluetooth, несколько сетевых карт и т. Д.).

Это делает работу, когда вы знаете IP-адрес iface, для которого вам нужен MAC, используя 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'
3 голосов
/ 02 октября 2008

Обратите внимание, что вы можете создать свою собственную кроссплатформенную библиотеку в python, используя условный импорт. например,

import platform
if platform.system() == 'Linux':
  import LinuxMac
  mac_address = LinuxMac.get_mac_address()
elif platform.system() == 'Windows':
  # etc

Это позволит вам использовать системные вызовы os.s или библиотеки для конкретной платформы.

2 голосов
/ 10 декабря 2016

Вы можете сделать это с помощью psutil, который является кроссплатформенным:

import psutil

mac_addresses = []

nics = psutil.net_if_addrs()
nics.pop('lo') # remove loopback since it doesnt have a real mac address

for i in nics:
    for j in nics[i]:
        if j.family == 17:  # AF_LINK
            mac_addresses.append(j.address)
1 голос
/ 02 августа 2018

Кроссплатформенный пакет getmac подойдет для этого, если вы не возражаете против зависимости. Работает с Python 2.7+ и 3.4+. Он будет пытаться использовать различные методы, пока не получит адрес или не вернет None.

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

Отказ от ответственности: я являюсь автором пакета.

Обновление (14 января 2019 г.): пакет теперь поддерживает только Python 2.7+ и 3.4+. Вы все еще можете использовать более старую версию пакета, если вам нужно работать со старым Python (2.5, 2.6, 3.2, 3.3).

0 голосов
/ 28 января 2019

С другой стороны,

import uuid
mac_id=(':'.join(['{:02x}'.format((uuid.getnode() >> ele) & 0xff)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...