I\'d like to get an id unique to a computer with Python on Windows and Linux. It could be the CPU ID, the motherboard serial, ... or anything else.
I looked at sever
How about using the MAC address as unique id?
The discussion here Obtain MAC Address from Devices using Python shows how to obtain the MAC address
UUID -Universally Unique Identifier
Python uuid module
[RFC 4122] A Universally Unique IDentifier (UUID) URN Namespace
for Windows you need DmiDecode for Windows (link) :
subprocess.Popen('dmidecode.exe -s system-uuid'.split())
for Linux (non root):
subprocess.Popen('hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.uuid'.split())
I don't think there is a reliable, cross platform, way to do this. I know of one network device that changes its MAC address as a form of hardware error reporting, and there are a million other ways this could fail.
The only reliable solution is for your application to assign a unique key to each machine. Yes it can be spoofed, but you don't have to worry about it completely breaking. If you are worried about spoofing you can apply some sort of heuristic (like a change in mac address) to try and determine if the key has been moved.
UPDATE: You can use bacterial fingerprinting.
Or if you don't want to use subprocess, (It's slow) use ctypes. This is for Linux non root.
import ctypes
from ctypes.util import find_library
from ctypes import Structure
class DBusError(Structure):
_fields_ = [("name", ctypes.c_char_p),
("message", ctypes.c_char_p),
("dummy1", ctypes.c_int),
("dummy2", ctypes.c_int),
("dummy3", ctypes.c_int),
("dummy4", ctypes.c_int),
("dummy5", ctypes.c_int),
("padding1", ctypes.c_void_p),]
class HardwareUuid(object):
def __init__(self, dbus_error=DBusError):
self._hal = ctypes.cdll.LoadLibrary(find_library('hal'))
self._ctx = self._hal.libhal_ctx_new()
self._dbus_error = dbus_error()
self._hal.dbus_error_init(ctypes.byref(self._dbus_error))
self._conn = self._hal.dbus_bus_get(ctypes.c_int(1),
ctypes.byref(self._dbus_error))
self._hal.libhal_ctx_set_dbus_connection(self._ctx, self._conn)
self._uuid_ = None
def __call__(self):
return self._uuid
@property
def _uuid(self):
if not self._uuid_:
udi = ctypes.c_char_p("/org/freedesktop/Hal/devices/computer")
key = ctypes.c_char_p("system.hardware.uuid")
self._hal.libhal_device_get_property_string.restype = \
ctypes.c_char_p
self._uuid_ = self._hal.libhal_device_get_property_string(
self._ctx, udi, key, self._dbus_error)
return self._uuid_
You can use this like:
get_uuid = HardwareUuid()
print get_uuid()
For python3.6 and windows must be used decode
>>> import subprocess
... current_machine_id = subprocess.check_output('wmic csproduct get uuid').decode().split('\n')[1].strip()
... print(current_machine_id)