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?
The order of catch statements is important. Put catch blocks targeted to specific exceptions before a general exception catch block or the compiler might issue an error. The proper catch block is determined by matching the type of the exception to the name of the exception specified in the catch block.
If a catch block handles multiple exceptions, you can separate them using a pipe (|) and in this case, exception parameter (ex) is final, so you can't change it. The byte code generated by this feature is smaller and reduce code redundancy.
You can also handle multiple exceptions using a single except clause by passing these exceptions to the clause as a tuple . except (ZeroDivisionError, ValueError, TypeError): print ( "Something has gone wrong.." ) Finally, you can also leave out the name of the exception after the except keyword.
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.
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]
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With