Search code examples
python-2.xwin32comsas-jmp

getting underlying OLE object identity for win32com automation objects


Most built-in Python data types and libraries make a point of returning the same object (a is b, not just a==b) even if you ask for it in different ways. A very simple example:

list = [ "foo", "bar", {"name": [1,2,3]} ]
a = list[-1]["name"]
b = list[2].values()[0]
print (a is b) # True!

However, this doesn't seem to be the case for many kinds of non-scalar objects returned by win32com automation. The following code connects to automation and then gets two handles to the same data table object. At the Python level, these two automation objects don't share an identity:

from win32com.client import gencache
mod = gencache.GetModuleForProgID("JMP.Application")
app = mod.Application()
table = app.GetTableHandleFromName("Table1")
same_table = app.GetTableHandleFromName("Table1")
print table
print same_table
print table is same_table
# <win32com.gen_py.DCD36DE0-78F8-11CF-9E68-0020AF24E9FEx0x1x0.IAutoDataTable instance at 0x54418504>
# <win32com.gen_py.DCD36DE0-78F8-11CF-9E68-0020AF24E9FEx0x1x0.IAutoDataTable instance at 0x54432456>
# False

It appears that all win32com OLE automation objects also have an _oleobj_ property. _oleobj_ is a PyIDispatch object, which only has a few methods, none of which seem pertinent to the question of object identity. However, the repr() of _oleobj_ seems to point to the underlying OLE automation object:

print table._oleobj_
print same_table._oleobj_
# <PyIDispatch at 0x0000000003459530 with obj at 0x00000000003E2928>
# <PyIDispatch at 0x0000000003459620 with obj at 0x00000000003E2928>

In order to confirm that two objects refer to the same underlying OLE object, I've resorted to parsing the repr() strings and comparing the hexadecimal addresses ("obj at 0x...").

Is there a better, cleaner way to compare OLE object identity using win32com?


Solution

  • *Smacks self in face*

    It turns out there's quite an easy way to do this: http://mail.python.org/pipermail/python-win32/2014-October/013288.html

    Although the is operator does not work since the Python objects are distinct, the == object accomplishes this purpose with win32com-wrapped objects:

    from win32com.client import gencache
    mod = gencache.GetModuleForProgID("JMP.Application")
    app = mod.Application()
    table = app.GetTableHandleFromName("Table1")
    same_table = app.GetTableHandleFromName("Table1")
    print table is same_table, table._oleobj_ is same_table._oleobj_
    print table==same_table, table._oleobj_==same_table._oleobj_
    # False, False
    # True, True