为什么我在使用win32com.client时突然出现了“没有属性'CLSIDToPackageMap'”的错误?

22

这段代码

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

曾经可用,但现在会产生错误:

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

发生了什么?

4个回答

49
在删除了C:\Temp\gen_py文件夹后,上述代码再次正常运行。希望这可以解决问题!

哦,我的天啊...就这么简单! - Ferrarezi
25
这个有效!对于我来说,相关的文件夹是“C:\ Users <我的用户名> \ AppData \ Local \ Temp \ gen_py”。 - Rafael Zayas
5
除了需要重新启动我的Jupyter内核之外,其他方面都非常成功。 - LotiLotiLoti
3
@RafaelZayas的路径是大多数人的"%TEMP%"。 - Leo
这真的救了我的命。我当时非常恐慌! - Oliver Bird

8
这个属性错误的主要原因是COM服务器从后期绑定(动态)转变为前期绑定(静态)。在后期绑定中,每次调用方法时都会查询对象是否存在该方法,如果成功,则可以进行调用。而在前期绑定中,对象模型的信息是提前确定的,这是通过对象调用所提供的类型信息进行的。前期绑定使用MakePy。此外,前期绑定区分大小写。
有两种方法可以解决这个问题:
  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()"
    

我猜,删除gen_py文件夹后第一次运行代码是有效的,但从第二次运行开始会抛出错误,因为win32.gencache.EnsureDispatch是一个早期绑定的Dispatch,所以gen_py文件夹会再次被创建。


2
我最近也遇到了同样的问题,删除gen_py文件夹后问题得到解决,而且没有再次出现。gen_py文件夹会被重新创建,但是在重新创建时已经修复了导致错误的原因。 - Doug Jenkins

7

我在Github讨论中找到了一种更优雅的解决方案,并将其合并到一个函数中。对我起作用了。

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 - Rob Irwin

-1

谢谢 - 在添加了您的函数并进行了此更改后,它像魔法一样奏效:

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

此致敬礼,

js


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接