16

I have a process that requires me to identify different machines, and I'm not sure what's the best way to do it. I do not want to save that ID on a text file or something, but I want to generate it from hardware every time I need it (in case the text with the ID gets deleted or something)

I've checked UUID, and it seems ok but I'm not sure. I've taken a look at uuid.getNode(), but I have 2 problems with it:

  1. One part says "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", which means that I may get a different unique on some systems for some reason - is there a way to identify which time it failed and generate something else?

  2. another part says: " “Hardware address” means the MAC address of a network interface, and on a machine with multiple network interfaces the MAC address of any one of them may be returned.", which means if i have 2 different network adapters, each call I may get any one of them? that's not good for me.

If you have a better way of obtaining a unique ID for a machine, that I can generate each time and won't have to worry about deletion of it or something - I'd be glad to hear it. all of my attempts to find something have failed. Thanks.

TzurEl
  • 792
  • 3
  • 9
  • 15
  • Duplicate question http://stackoverflow.com/questions/2461141/get-a-unique-computer-id-in-python-on-windows-and-linux – nu everest Feb 26 '17 at 23:35
  • This is a duplicate question to this: https://stackoverflow.com/questions/2461141/get-a-unique-computer-id-in-python-on-windows-and-linux/45096068#45096068 Check this: https://stackoverflow.com/a/45096068/3759901 – Souvik Jul 14 '17 at 06:28

7 Answers7

21

Please note that you can get the same UUID from Windows without installing any additional software with the following command:

C:\> wmic csproduct get uuid
nauj27
  • 311
  • 2
  • 4
  • 7
    Use subprocess to run it from your python code: import subprocess current_machine_id = subprocess.check_output('wmic csproduct get uid').split('\n')[1].strip() – Souvik Jul 14 '17 at 06:30
  • CalledProcessError: Command 'wmic csproduct get uid' returned non-zero exit status -2147217385 – Mostafa Feb 28 '19 at 03:46
  • Thats a very good answer and even a better comment from Souvik – Rishav Apr 22 '19 at 16:53
  • 1
    Small typo in Souvik comment. Use `import subprocess current_machine_id = subprocess.check_output('wmic csproduct get uuid').split('\n')[1].strip()` (uuid instead of uid) :-) – tim May 22 '20 at 08:03
  • Fixing typo from @tim. `current_machine_id = subprocess.check_output('wmic csproduct get uuid').split(b'\n')[1].strip()` You have to split a byte with a byte. – binary_assemble Oct 03 '22 at 01:15
  • python 3 : `subprocess.check_output('wmic csproduct get uuid').decode("utf-8").split('\n')[1].strip()` – Abdelouahab Mar 12 '23 at 22:18
11

You could use dmidecode.

Linux:

import subprocess

def get_id():
    return subprocess.Popen('hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.uuid'.split())

Windows:
NOTE: Requires dmidecode for Windows

import subprocess

def get_id():
    return subprocess.Popen('dmidecode.exe -s system-uuid'.split())

Cross-platform:
NOTE: Requires dmidecode for Windows

import subprocess
import os

def get_id():
    if 'nt' in os.name:
        return subprocess.Popen('dmidecode.exe -s system-uuid'.split())
    else:
        return subprocess.Popen('hal-get-property --udi /org/freedesktop/Hal/devices/computer --key system.hardware.uuid'.split())
theB
  • 6,450
  • 1
  • 28
  • 38
Ciprum
  • 734
  • 1
  • 11
  • 18
  • Thank you! that was very helpful. using dmidecode is an excellent idea. (didn't know this) – TzurEl Jul 13 '16 at 07:38
  • Linux update 2020: HAL is ancient Linux history. Use `dmidecode -s system-uuid` instead. – VPfB Sep 03 '20 at 07:06
4

For windows this seems to get same uuid every time por each device based on the MAC address:

str(uuid.uuid1(uuid.getnode(),0))[24:]

But it does not seem to keep same ID on Android 4.4.2.

Jorge
  • 57
  • 7
  • for some reason on the same machine but different python versions `str(uuid.uuid1(uuid.getnode(),0))` returns different 8 first letters and the others the same, be aware if you want to use the full UUID and use different python versions. – Ohad Cohen Mar 08 '22 at 10:45
2

This worked for me:

import subprocess

current_machine_id = str(subprocess.check_output('wmic csproduct get uuid'), 'utf-8').split('\n')[1].strip()

print(current_machine_id)
Mayur Patil
  • 139
  • 2
  • 5
2

After seeing this question asked quite a few times both here on SO as well as in support requests for my software licensing business (called Keygen), I wrote a small, cross-platform PyPI package that queries a machine's native GUID called machineid.

Essentially, it looks like this, but with some Windows-specific WMI registry queries for more a accurate ID. The package also has support for hashing the ID, to anonymize it.

import subprocess
import sys

def run(cmd):
  try:
    return subprocess.run(cmd, shell=True, capture_output=True, check=True, encoding="utf-8") \
                     .stdout \
                     .strip()
  except:
    return None

def guid():
  if sys.platform == 'darwin':
    return run(
      "ioreg -d2 -c IOPlatformExpertDevice | awk -F\\\" '/IOPlatformUUID/{print $(NF-1)}'",
    )

  if sys.platform == 'win32' or sys.platform == 'cygwin' or sys.platform == 'msys':
    return run('wmic csproduct get uuid').split('\n')[2] \
                                         .strip()

  if sys.platform.startswith('linux'):
    return run('cat /var/lib/dbus/machine-id') or \
           run('cat /etc/machine-id')

  if sys.platform.startswith('openbsd') or sys.platform.startswith('freebsd'):
    return run('cat /etc/hostid') or \
           run('kenv -q smbios.system.uuid')
ezekg
  • 924
  • 10
  • 20
1

The ideal approach which I resorted to was this. It is quite fast and efficient.

hwid = str(subprocess.check_output(
    'wmic csproduct get uuid')).split('\\r\\n')[1].strip('\\r').strip()
data = requests.get(
    'https://gist.githubusercontent.com/rishav394/z/raw/x')
if hwid in data.text:
    print('Authenticated!')
    auth = True
else:
    print(hwid + ' was not found on the server.\nNot authorised!')
Rishav
  • 3,818
  • 1
  • 31
  • 49
-1

or use bios serialnr

wmic bios get serialnumber