22

The code

import win32com.client as win32 
Excel = win32.gencache.EnsureDispatch('Excel.Application') 

used to work, but now it produces the error:

AttributeError: 'module' object has no attribute 'CLSIDToPackageMap'

what's going on?

Davide Fiocco
  • 5,350
  • 5
  • 35
  • 72
theVerse
  • 904
  • 1
  • 7
  • 14

4 Answers4

48

After deleting C:\Temp\gen_py, the code above works again. Hope it can save trouble!

theVerse
  • 904
  • 1
  • 7
  • 14
8

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.Dispatch()" instead of "win32.gencache.EnsureDispatch('Excel.Application')" 
    
  2. Use camelcase sensitive keywords for the early bound oriented way. Example use:

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

I guess, the code works for the first run after deleting gen_py folder but from the second run throws an error as win32.gencache.EnsureDispatch being an early binding Dispatch, gen_py folder will be created again.

Bharat Sesham
  • 416
  • 4
  • 11
  • 2
    I recently had the same problem, and deleting gen_py fixed it, with no recurrence. The gen_py folder is recreated, but whatever was causing the error was fixed when it was recreated. – Doug Jenkins Nov 25 '18 at 22:01
7

I found a more elegant solution on a Github discussion and incorporated it into a function. Worked for me.

def dispatch(app_name:str):
    try:
        from win32com import client
        app = client.gencache.EnsureDispatch(app_name)
    except AttributeError:
        # Corner case dependencies.
        import os
        import re
        import sys
        import shutil
        # Remove cache and try again.
        MODULE_LIST = [m.__name__ for m in sys.modules.values()]
        for module in MODULE_LIST:
            if re.match(r'win32com\.gen_py\..+', module):
                del sys.modules[module]
        shutil.rmtree(os.path.join(os.environ.get('LOCALAPPDATA'), 'Temp', 'gen_py'))
        from win32com import client
        app = client.gencache.EnsureDispatch(app_name)
    return app
pelelter
  • 518
  • 4
  • 14
-1

Thanks - worked like a charm after adding your function and making this change:

#excel = win32.gencache.EnsureDispatch('Excel.Application')    
excel = dispatch('Excel.Application')

Sincerely,

js