'Python DispatchWithEvents results in attribute error:

Using dispatch as win32com.client.Dispatch works fine, but produces attribute error: from DispatchWithEvents call win32com.client.WithEvents, problem exists until Temp\gen_py folder is removed

I can remove the Temp\gen_py folder at the very beginning before import win32com.client

path=r"C:\Users\omc\AppData\Local\Temp\gen_py"
rmtree(path, ignore_errors=True)
while os.path.exists(path):
    pass

works fine for the 1st iteration in my test, but for the 2nd iteration for the same code produces attribute error:

from shutil import rmtree
path=r"C:\Users\omc\AppData\Local\Temp\gen_py"
rmtree(path, ignore_errors=True)
while os.path.exists(path):
    pass
import win32com.client

class CanoeTestModuleEvents(object):
    """Handler for CANoe TestModule events"""
    def OnStart(self): 
        print("< Test Module started >")
        bTestModuleRunning = True
    def OnStop(self,Reason) : 
        print("< Test Module stopped >")
        bTestModuleRunning = False
        if Reason == 0:
            print("Test module was executed completely")
        else:
            if Reason== 1:
                print("Test module was stopped by the user")
            else:
                print("Test module was stopped by measurement stop")


APP = win32com.client.Dispatch("CANoe.Application")
App.load("CANoeApplication.cfg")

# ---------------------------------------------------------------
# TestEnvironment Item(2)
# ---------------------------------------------------------------
TestEnvironment = self.App.Configuration.TestSetup.TestEnvironments.Item(1)
TestModule = self.TestEnvironment.Items.Item(2)
TestModule.TestVariant = TestVariant
App.Measurement.Start()
WaitForMeasurementStart()

win32com.client.WithEvents(TestModule, CanoeTestModuleEvents)
if MeasurementRunning():
            TestModule.Start()
            WaitForTestModuleStart()

while app.bTestModuleRunning == True:
    pythoncom.PumpWaitingMessages()
    time.sleep(.1)

App.Measurement.Stop()

# ---------------------------------------------------------------
# TestEnvironment Item(3)
# ---------------------------------------------------------------
TestEnvironment = self.App.Configuration.TestSetup.TestEnvironments.Item(1)
TestModule = self.TestEnvironment.Items.Item(3)
TestModule.TestVariant = TestVariant
App.Measurement.Start()
WaitForMeasurementStart()

win32com.client.WithEvents(TestModule, CanoeTestModuleEvents)
if MeasurementRunning():
            TestModule.Start()
            WaitForTestModuleStart()

while app.bTestModuleRunning == True:
    pythoncom.PumpWaitingMessages()
    time.sleep(.1)

App.Measurement.Stop()

AttributeError: object has no attribute

AttributeError: '<win32com.gen_py.CANoe 8.5 Type Library.ITestSetupItem instance at 0x49756368>' object has no attribute 'TestVariant'


Solution 1:[1]

The main reason for this attribute error is because your COM-server has shifted from late-binding (dynamic) to early binding (static).

  • In Late Binding, whenever a method is called, the object is queried for the method and if it succeeds, then the call can be made.
  • In Early Binding, the information of the object model is determined in advance from type information supplied by the object call. Early binding makes use of MakePy. Also, early binding is case sensitive.

There are two ways to fix this issue:

  1. Use the dynamic module to force your code to work in a late-bound oriented way. Example use:

    "win32com.client.dynamic.Dispatch()" instead of "win32com.client.Dispatch()" 
    
  2. Use camelcase sensitive keywords for the early bound oriented way. Example use:

    "excel.Visible()" instead of "excel.VISIBLE()" or "excel.visible()"
    

Also, I think using early binding dependent methods by default create the gen_py folder every time.

Solution 2:[2]

Actually the problem here is that for some reason you need to cast the objects

csbTstMod = win32com.client.CastTo(csbTstMod, "ITSTestModule3")
print(csbTstMod.TestVariant)

This will now work.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bharat Sesham
Solution 2 Jeremy Caney