15

I am writing a Python program that interfaces with Quickbooks. When connecting to Quickbooks, depending on the problem, I might get one of two common exceptions:

pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'QBXMLRP2.RequestProcessor.2', 'The QuickBooks company data file is currently open in a mode other than the one specified by your application.', None, 0, -2147220464), None)

pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'QBXMLRP2.RequestProcessor.2', 'Could not start QuickBooks.', None, 0, -2147220472), None)

Catching the generic exception with except Exception as e shows that the type of e is <class 'pywintypes.com_error'>, which cannot be used to catch an exception:

... catch pywintypes.com_error as e:
NameError: global name 'pywintypes' is not defined

So how might I catch these two exceptions in a non-generic manner? Ideally the code would have this layout:

try:
    qb = qbsdk_interface.Qbsdk_Interface(QB_FILE)

except QbWrongModeError as e:
    print('Quickbooks is open in the wrong mode!')

except QbClosedError as e:
    print('Quickbooks is closed!')

except Exception as e:
    print('Something else went wrong!')

Of course, the exceptions QbWrongModeError and QbClosedError do not exist, so what should be there in their place?

dotancohen
  • 30,064
  • 36
  • 138
  • 197
  • This might be relevant: http://stackoverflow.com/questions/9203336/python-pythoncom-com-error-handling-in-python-3-2-2 – Korem Jul 31 '14 at 08:10
  • Yes, it certainly is. Another similar one cam up in the Related links on the right as well. Figures: half an hour searching and I find nothing, and even the suggestions based on title came up with nothing while I was writing the question. But the Related sidebar finds them right away! – dotancohen Jul 31 '14 at 08:12

3 Answers3

20

As soon as I posted I found the way to catch the exception in a non-generic manner in a question that appeared in the Related sidebar. Here is the way to capture these exceptions:

from pywintypes import com_error

except com_error as e:

Note that the differing reasons for the exception cannot be handled individually, so the return code must be examined inside the except clause by comparing the value of e.exceptinfo[5]:

except com_error as e:

    if e.excepinfo[5] == -2147220464:
        print('Please change the Quickbooks mode to Multi-user Mode.')

    elif e.excepinfo[5] == -2147220472:
        print('Please start Quickbooks.')

    else:
        raise e

I had considered marking this question as a dupe, but considering that none of the other related questions handle the situation of distinguishing between the different exceptions thrown under this single type, I leave this one as it addresses this issue and answers it.

Community
  • 1
  • 1
dotancohen
  • 30,064
  • 36
  • 138
  • 197
  • 2
    `e.excepinfo` doesn't have the return code in some versions of `pywintypes`, but `e.hresult` does. – AlexM Jul 08 '20 at 03:35
  • 1
    @AlexM It seems that my com_errors do not have hresult. I get an AttributeError. – PProteus Aug 10 '20 at 13:59
  • 1
    Exactly. We're using different versions of `pwintypes`, and my comment is there to help people no matter which version they have. – AlexM Aug 10 '20 at 14:31
14

Now pywintypes.error is BaseException.

There is no need to from pywintypes import com_error.

If you want to catch this exception. You can just catch BaseException

except BaseException as e: # to catch pywintypes.error
    print(e.args)

the exception's format likes this:

(0, 'SetForegroundWindow', 'No error message is available')

So If you want to examine the return code,use e.args[0] instead of e.exceptinfo[5]

jizhihaoSAMA
  • 12,336
  • 9
  • 27
  • 49
2

Just wanted to add something to @jizhihaoSAMA's answer from @dotancohen's answer for added clarity.

You may want to raise any other errors that you're not expecting when catching a specific BaseException. Otherwise the code will just finish but not do what you're expecting.

except BaseException as e:  # to catch pywintypes.error
    if e.args[0] == -2147352567:
        print(my_str)
    else:
        raise e
PyHP3D
  • 88
  • 10