特に 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
また、それを持っているので、拡張エラー コード (-2146788248) に対しても fix_com_hresult() を実行する必要がありますが、Euro Micelli が言ったように、この特定のインスタンスでは役に立ちません :)