特别是对于 pythoncom,产生的错误代码不仅仅是神秘的。这是因为当正确的表示是 32 位无符号整数时,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 位有符号整数,然后将其解释为无符号整数:
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 所说,它在这个特定情况下对你没有帮助:)