The other day in the comments, A asked about some Python I had posted a few years ago: Why did I manually dispatch XSI.Factory instead of just using the global XSIFactory object? Honestly, I don’t know why I did. I had seen other code do it that way, so I did it too. And I see that the sipyutils.py also dispatches objects like XSI.Application, XSI.Utils, and XSI.Math, so I figured I was in good company.
A little research shows that XSIFactory uses late bound automation (aka dynamic dispatch) and so avoids any possible problems with the pywin32 cache. Late-bound automation means that PythonCOM doesn’t know what properties or methods the object supports; whenever you try to access a property or method, PythonCOM will query the object to find out if the property/method is supported.
In contrast, when you dispatch XSI.Factory, PythonCOM uses the pywin32 cache to support early-binding, where all the available properties and methods are known beforehand.
You can read more about this Chapter 12 of Python Programming on Win32, Advanced Python and COM
Here’s a little Python snippet demonstrating the differences between a dispatched XSI.Factory and the global XSIFactory object. Note in particular the output of dir() for each object.
from win32com.client import Dispatch as disp sifact = disp('XSI.Factory') print sifact print XSIFactory # <win32com.gen_py.Softimage|XSI Object Model Library v1.5.XSIFactory instance at 0x564246344> # <COMObject XSIFactory> print dir(sifact) print dir(XSIFactory) # ['CLSID', 'CreateActiveXObject', 'CreateFCurveKeyCollection', 'CreateFCurveParamDef', 'CreateGridData', 'CreateGridParamDef', 'CreateGuid', 'CreateObject', 'CreateObjectFromFile', 'CreateObjectFromFile2', 'CreateObjectFromPreset', 'CreateObjectFromPreset2', 'CreateParamDef', 'CreateParamDef2', 'CreateScriptedOp', 'CreateScriptedOpFromFile', 'CreateShaderDef', 'CreateShaderParamDefOptions', 'RemoveShaderDef', '_ApplyTypes_', '__doc__', '__eq__', '__getattr__', '__init__', '__module__', '__ne__', '__repr__', '__setattr__', '_get_good_object_', '_get_good_single_object_', '_oleobj_', '_prop_map_get_', '_prop_map_put_', 'coclass_clsid'] # ['_Close_', '__doc__', '__getattr__', '__init__', '__module__', '__repr__', '__setattr__', '_scriptItem_'] print sifact.__module__ print XSIFactory.__module__ # win32com.gen_py.269C4D8C-E32D-11D3-811D-00A0C9AC19A9x0x1x0.XSIFactory # win32com.axscript.client.pyscript