Специально для pythoncom коды ошибок, которые в результате получаются более чем загадочными. Это связано с тем, что pythoncom представляет их внутренне как 32-битное целое число со знаком, когда правильное представление представляет собой 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
Итак, чтобы собрать все это вместе, вам нужно запускать fix_com_hresult () для этого результата из pythoncom, по сути, постоянно.
Так как обычно вам нужно делать это при проверке исключений, я создал следующие функции:
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
Мне не удалось найти документ MSDN со списком всех HRESULT, но я нашел это: http://www.megos.ch/support/doserrors_e.txt
Кроме того, поскольку у вас это есть, fix_com_hresult () также следует запускать для вашего расширенного кода ошибки (-2146788248), но, как сказал Euro Micelli, в данном конкретном случае это не поможет:)