[Python-Dev] UUID module

Thomas Heller theller at python.net
Sat Jun 10 17:11:15 CEST 2006


Ka-Ping Yee wrote:
> Finally, Phillip brought up PEAK:
>> PEAK's uuid module does this such that if win32all is present,
>> you get a Windows GUID, or if you have a FreeBSD 5+ or
>> NetBSD 2+ kernel you use the local platform uuidgen API.  See e.g.:
> 
> ...so i looked at PEAK's getnodeid48() routine and borrowed the
> Win32 calls from there, with a comment giving attribution to PEAK.
> 
> Oh, and there is now a test suite that should cover all the code paths.
> 
> This is all posted at http://zesty.ca/python/uuid.py now,
> documentation page at http://zesty.ca/python/uuid.html,
> tests at http://zesty.ca/python/test_uuid.py .

(From http://zesty.ca/python/uuid.py:)

def win32_getnode():
    """Get the hardware address on Windows using Win32 extensions."""
    try:
        import pywintypes
        return int(pywintypes.CreateGuid()[-13:-1], 16)
    except:
        pass
    try:
        import pythoncom
        return int(pythoncom.CreateGuid()[-13:-1], 16)
    except:
        pass



This does not work, for several reasons.

1. (pythoncom|pywintypes).CreateGuid() return a PyIID instance, which you cannot slice:

>>> import pywintypes
>>> pywintypes.CreateGuid()
IID('{4589E547-4CB5-4BCC-A7C3-6E88FAFB4301}')
>>> type(pywintypes.CreateGuid())
<type 'PyIID'>
>>> pywintypes.CreateGuid()[-13:-1]
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
TypeError: unsubscriptable object
>>>

So, you would have to change your code to 'str(pythoncom.CreateGuid())[-13:-1]'.

(BTW: Why does it first try pywintypes, the pythoncom?)

2. These functions call to win32 CoCreateGuid function, which create a new uuid.
As documented on MSDN, this calls the UuidCreate function which:

"The UuidCreate function generates a UUID that cannot be traced to the ethernet/token ring
address of the computer on which it was generated."

In other words, the last 12 characters do *not* identify the mac address, in fact your function,
if repaired, returns a different result each time it is called.  See this link for
further info:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/uuidcreate.asp

A possible solution, if you really need the mac address, is to call the UuidCreateSequential
function where available (W2k, XP, ...), and UuidCreate on older systems (W98, ME).
Link to MSDN:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rpc/rpc/uuidcreatesequential.asp

3. Now that ctypes is part of Python, why not use it?  This snippet of code
displays the mac address of one of the ethernet adapters I have in my machine:

from ctypes import *
import binascii

class UUID(Structure):
    _fields_ = [("Data1", c_ulong),
                ("Data1", c_ushort),
                ("Data1", c_ushort),
                ("Data1", c_ubyte * 8)]

def CreateGuid():
    uuid = UUID()
    if 0 == windll.rpcrt4.UuidCreateSequential(byref(uuid)):
        return str(buffer(uuid))

print binascii.hexlify(CreateGuid()[-6:])

It should be extended to also work on w98 or me, probably.

Thomas



More information about the Python-Dev mailing list