Responder a la pregunta con Python depende de su plataforma. No tengo Windows a mano, así que la siguiente solución funciona en la caja de Linux en la que la escribí. Un pequeño cambio en la expresión regular lo hará funcionar en OS X.
Primero, debe hacer ping al destino. Eso colocará el objetivo, siempre y cuando esté dentro de su máscara de red, lo que suena en esta situación, en el caché ARP de su sistema. Observe:
13:40 [email protected]% ping 97.107.138.15
PING 97.107.138.15 (97.107.138.15) 56(84) bytes of data.
64 bytes from 97.107.138.15: icmp_seq=1 ttl=64 time=1.25 ms
^C
13:40 [email protected]% arp -n 97.107.138.15
Address HWtype HWaddress Flags Mask Iface
97.107.138.15 ether fe:fd:61:6b:8a:0f C eth0
Sabiendo eso, haces un poco de magia subproceso - de lo contrario se está escribiendo caché ARP código de comprobación de sí mismo, y no quiere hacer eso:
>>> from subprocess import Popen, PIPE
>>> import re
>>> IP = "1.2.3.4"
>>> # do_ping(IP)
>>> # The time between ping and arp check must be small, as ARP may not cache long
>>> pid = Popen(["arp", "-n", IP], stdout=PIPE)
>>> s = pid.communicate()[0]
>>> mac = re.search(r"(([a-f\d]{1,2}\:){5}[a-f\d]{1,2})", s).groups()[0]
>>> mac
"fe:fd:61:6b:8a:0f"
Él está evitando ARP gratuito, no comprobar las cosas en la máquina local. Lea la pregunta cuidadosamente: ** desde un dispositivo en mi red local ** –