特别是对于 pythoncom,产生的错误代码不仅仅是神秘的。这是因为当正确的表示是 32 位 unsigned 整数时,pythoncom 在内部将它们表示为 32 位有符号整数。因此,您最终在堆栈跟踪中看到的转换是不正确的。
特别是,根据 pythoncom,您的例外是 -2147352567,而您的(因为没有更好的词) Err.Number 是 -2146788248。
然而,这在查看特定错误时会导致一些问题,如下所示:
DISP_E_EXCEPTION = 0x80020009
#...
#except pywintypes.com_error as e:
# print repr(e)
# #pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146788248), None)
# hr = e.hresult
hr = -2147352567
if hr == DISP_E_EXCEPTION:
pass #This never occurs
else:
raise
要了解为什么会出现问题,让我们看看这些错误代码:
>>> DISP_E_EXCEPTION = 0x80020009
>>> DISP_E_EXCEPTION
2147614729L
>>> my_hr = -2147352567
>>> my_hr == DISP_E_EXCEPTION
False
同样,这是因为 python 将常量视为正数,而 pythoncom 的错误声明将其解释为负数。当然,最明显的解决方案失败了:
>>> hex(my_hr)
'-0x7ffdfff7'
解决方案是正确解释数字。幸运的是,pythoncom 的表示是可逆的。我们需要将负数解释为 32 位有符号整数,然后将 that 解释为无符号整数:
def fix_com_hresult(hr):
import struct
return struct.unpack("L", struct.pack("l", hr))[0]
>>> DISP_E_EXCEPTION = 0x80020009
>>> my_hr = -2147352567
>>> my_hr == DISP_E_EXCEPTION
False
>>> fixed_hr = fix_com_hresult(my_hr)
>>> fixed_hr
2147614729L
>>> fixed_hr == DISP_E_EXCEPTION
True
因此,综合起来,您需要对来自 pythoncom 的结果运行 fix_com_hresult(),基本上是一直运行。
由于在检查异常时通常需要这样做,所以我创建了这些函数:
def fix_com_exception(e):
e.hresult = fix_com_hresult(e.hresult)
e.args = [e.hresult] + list(e.args[1:])
return e
def fix_com_hresult(hr):
import struct
return struct.unpack("L", struct.pack("l", hr))[0]
然后可以按照您的期望使用:
DISP_E_EXCEPTION = 0x80020009
try:
#failing call
except pywintypes.com_error as e:
print repr(e)
#pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146788248), None)
fix_com_exception(e)
print repr(e)
#pywintypes.com_error: (2147614729L, 'Exception occurred.', (0, None, None, None, 0, -2146788248), None)
if e.hresult == DISP_E_EXCEPTION:
print "Got expected failure"
else:
raise
我找不到列出所有 HRESULT 的 MSDN 文档,但我找到了:http://www.megos.ch/support/doserrors_e.txt
另外,既然你有它,fix_com_hresult() 也应该在你的扩展错误代码 (-2146788248) 上运行,但正如 Euro Micelli 所说,它在这种特定情况下对你没有帮助:)