这是最近运行的一个用Python编写的不可靠应用程序的堆栈跟踪的一部分,该应用程序控制用Excel编写的另一个应用程序:
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146788248), None)
显然出现了问题...但是什么?[1]这些COM错误代码似乎过于神秘.
如何解码此错误消息?是否有一个表允许我将这个数字错误代码转换为更有意义的东西?
[1]我实际上知道在这种情况下出了什么问题,它试图访问一个没有Name属性的Range对象上的Name属性...并不是所有的bug都很容易找到!
你没有做错任何事.堆栈跟踪中的第一项(数字)是COM对象返回的错误代码.第二项是与错误代码相关的描述,在这种情况下是"Exception Occurred".pywintypes.com_error已经为你调用了相当于win32api.FormatMessage(errCode)的东西.我们将在一分钟内查看第二个数字.
顺便说一下,您可以使用Visual Studio中的"错误查找"实用程序(C:\ Program Files\Microsoft Visual Studio 9.0\Common7\Tools\ErrLook.exe)作为快速启动板来检查COM错误代码.该实用程序还为您调用FormatMessage并显示结果.并非所有错误代码都适用于此机制,但很多人会这样做.这通常是我的第一站.
COM中的错误处理和报告有点乱.我会试着给你一些背景知识.
所有COM方法调用都将返回一个名为HRESULT的数字代码,可以指示成功或失败.COM中的所有形式的错误报告都是基于此构建的.
代码通常以十六进制表示,但有时您会将它们视为大型32位数字,就像在堆栈跟踪中一样.有针对常见结果和问题的各种预定义返回码,或者对象可以在特殊情况下返回自定义数字代码.例如,值0(称为S_OK)通用表示"无错误",0x80000002表示E_OUTOFMEMORY.有时HRESULT代码由对象返回,有时由COM基础结构返回.
COM对象还可以通过实现名为IErrorInfo的接口来选择提供更丰富的错误信息.当一个对象实现IErrorInfo时,它可以提供有关所发生事件的各种详细信息,例如详细的自定义错误消息,甚至是描述问题的帮助文件的名称.在VB6和VBA中.该Err
对象允许您访问所有信息(Err.Description
等).
更复杂的是,后期绑定的COM对象(使用名为COM Automation或IDispatch的机制)添加了一些需要剥离的层以获取信息.Excel通常通过后期绑定来操纵.
现在让我们再看看你的情况.你得到的第一个数字是一个相当通用的错误代码:DISP_E_EXCEPTION.注意:您通常可以通过Google搜索数字找出HRESULT的官方名称,但有时您必须使用十六进制版本来查找有用的内容.
以DISP_开头的错误是IDISPATCH错误代码.错误松散地意味着"对象抛出了一个COM异常",其他地方包含更多信息(虽然我不知道在哪里;我必须查找它).
根据我对pywintypes.com_error的理解,消息中的最后一个数字是异常期间对象返回的实际错误代码.这是你从VBA获得的实际数字代码Err.Number
.
不幸的是,第二个代码-2146788248(0x800A9C68)在为自定义应用程序定义的错误消息(在VBA中VbObjectError + someCustomErrorNumber
)保留的范围内,因此没有集中的含义.对于不同的程序,相同的数字可能意味着完全不同的事
在这种情况下,我们已达到死胡同:
错误代码是"自定义",应用程序需要记录它是什么,除了Excel没有.此外,Excel(或错误的实际来源)似乎没有通过IErrorInfo提供任何更多信息.
Excel(至少对我来说)因自动化和造成它们的模糊情况而产生的神秘错误代码是臭名昭着的.对于可以考虑"设计时错误"的错误尤其如此("你应该知道比调用对象中不存在的方法更好").您可以获得" 运行时错误'1004':应用程序定义或对象定义错误 "(我刚刚尝试从VBA访问Range上的Name属性而获得)而不是一个很好的"无法读取Name属性" 在Excel中).这不是很有帮助.
问题不是在Python或它的Excel界面上路由的.Excel本身并没有解释发生了什么,甚至VBA.
但是,上述一般程序仍然有效.如果将来从Excel收到错误,您可能会收到更好的错误消息,您可以以相同的方式跟踪.
祝好运!
像这样做:
try: [whatever code] except pythoncom.com_error as error: print(win32api.FormatMessage(error.excepinfo[5]))
有关消化pythoncom.com_error对象的更多信息,请访问:http://docs.activestate.com/activepython/3.2/pywin32/com_error.html
是的尝试win32api模块:
import win32api e_msg = win32api.FormatMessage(-2147352567)
您可以获取从异常返回的任何代码并将它们传递给FormatMessage.您的示例有2个错误代码.