python exception from module is not caught - python

I tried to catch an exception from vk_api module. I imported it:
import vk_api
then wrote some code, and then i screwed up my token on purpose so i can check if exception catch works:
try:
vk.method('wall.post', params)
except vk_api.exceptions.ApiError:
print('caught')
but it still gives me an error:
vk_api.exceptions.ApiError: [5] User authorization failed: invalid access_token (4).
What's the problem?

Your error comes from somewhere else in your code. You can have a better idea of where it comes from by using a wider try/except block.

try:
vk_session.auth(token_only=True)
except vk_api.AuthError as error_msg:
print(error_msg)
return
You can check it out an example here.
It seems the correct usage is vk_api.[ErrorName]
Your answer is
try:
vk.method('wall.post', params)
except vk_api.ApiError:
print('caught')

Related

How to catch PyGetWindowException when using pygetwindow in Python?

I have a script which uses pygetwindow module to do some operations on a specific window. While the script runs, I get the following exception:
File "C:\Program Files (x86)\Python38-32\lib\site-packages\pygetwindow\_pygetwindow_win.py", line 237, in activate
_raiseWithLastError()
File "C:\Program Files (x86)\Python38-32\lib\site-packages\pygetwindow\_pygetwindow_win.py", line 97, in _raiseWithLastError
raise PyGetWindowException('Error code from Windows: %s - %s' % (errorCode, _formatMessage(errorCode)))
pygetwindow.PyGetWindowException: Error code from Windows: 0 - The operation completed successfully.
I'm okay with the exception occurring but I want to catch this exception explicitly. I have done the following to try and catch this exception:
try:
#implementation
except pygetwindow.PyGetWindowException:
#handle exception
and
try:
#implementation
except PyGetWindowException:
#handle exception
Neither of the above catches the exception. If I use either of the above, I get another exception:
NameError: name 'PyGetWindowException' is not defined
or
NameError: name 'pygetwindow' is not defined
I don't want to catch the general Exception and then handle it since in case of other exceptions, I want to handle it differently. Is there something wrong in how I'm trying to catch this exception or is there a way to avoid this exception altogether?
EDIT: To be very clear, I have already imported pygetwindow.
You should have import pygetwindow at the begging of your script. It complains about not knowing what pygetwindow is.
Update
From the source file, it was clear that in order to use PyGetWindowException, you need to import the exception specifically (and not just import pygetwindow). Therefore, in order to catch the exception, one will have to do:
from pygetwindow import PyGetWindowException
After this import, you can use the exception in the normal way:
try:
#implementation
except PyGetWindowException:
#handle exception
Update 2
Another general way to do this would be to get the exception name from general exception and compare.
try:
try:
#implementation
except Exception as e:
if e.__class__.__name__ == 'PyGetWindowException':
#handle exception
else:
raise e
except Exception as e:
#handle other exceptions except pygetwindow exception
Original answer (not recommended)
Found a way to solve this question in this answer.
From the source of pygetwindow, it was clear that, whenever PyGetWindowException is raised, it is accompanied by the text:
"Error code from Windows:"
which indicates the error code given by Windows.
Based on this information, I did the following:
try:
try:
#Implementation
except Exception as e:
if "Error code from Windows" in str(e)
# Handle pygetwindow exception
else:
raise e
except Exception as e:
#handle other exceptions
This is another way (although the first one and second one are the correct and straightforward solutions) to solve the problem.

Repacking or wrapping of imported error or exception types in python3 modules

I have this module A that might raise an exception from an imported module B. Can I "wrap" or "repack" the exception so that I can handle the exception in the importing script without having to import B?
A.py:
import B
def do_something(parameters):
try:
B.function(**parameters)
except B.some_exception as eee:
raise wrapper(eee)
script.py
import A
try:
do_something("glorious parameter")
except B.wrapped_exception:
handling()
You could just import the exception from B like
from B import some_exception
or add a general exception catch with some other logic, like a matching message, to check if it the specific exception like
try:
do_something("glorious parameter")
except Exception as e:
if str(e) == "Matching message":
handling()
else:
raise e
However, bare exceptions are usually not recommended because they indiscriminately catch everything (What is wrong with using a bare 'except'?) so I would go with your original solution or the first suggestion.
Edit:
I re-read your issue and I think I got what you meant. You can chain exceptions with the keyword from and raise some general error like ValueError such as:
def do_something(parameters):
try:
B.function(**parameters)
except B.some_exception as eee:
raise ValueError("Wrapped exception") from eee
and then catch the ValueError as usual.
See: Python "raise from" usage

raise custom exception in python

I could not get what is wrong with the code ? when I execute nothing happens. I am expecting my custom error message.
def testing():
try:
raise Exception('My error!')
except:
pass
testing()
You are raising an exception successfully. But you are catching that with try/except block. So nothing happens unless you describe it in except block.
You are successfully raising an error. And the try/catch statements sees it, and goes to catch as you have raised an error.
To fully customize errors you can declare them as so:
class CustomError(Exception):
pass
raise CustomError("An error occurred")
results in
__main__.CustomError: An error occurred

Exception not being caught in try-except block during unit test

I have this in my code:
import api
def do_something():
try:
api = api.Api()
api.call()
except ParseException as e:
logger.exception('Error occurred')
raise ValidationError(detail=e.message)
Basically it calls an API and re-raises the exception with another type.
My test checks the case when the exception is thrown:
#patch('code.api')
def test_exception(self, api_mock):
api_mock.Api.side_effect = ParseException('General Error')
self.assertRaises(
ValidationError,
do_something
)
api_mock.Api.assert_called_once()
However my test fails because ParseException gets thrown and not ValidationError. What is going on?
Note the #patch('code.api') line. This says patch EVERYTHING in code.api. The ParseException is probably in the api module too and thus patched too. If you debug your code you'll see that type(ParseException) is not an instance of Exception but an instance of MagicMock.
I just spent an hour banging my head on the desk, hope this helps someone.

Print Python Exception Type (Raised in Fabric)

I'm using Fabric to automate, including the task of creating a directory. Here is my fabfile.py:
#!/usr/bin/env python
from fabric.api import *
def init():
try:
local('mkdir ./www')
except ##what exception?##:
#print exception name to put in above
Run fab fabfile.py and f I already have ./www created an error is raised, but I don't know what kind, so I don't know how to handle the error yet. Fabric only prints out the following:
mkdir: cannot create directory ‘./www’: File exists
Fatal error: local() encountered an error (return code 1) while executing 'mkdir ./www'
Aborting.
What I want to do is be able to find out the error type so that I can except my errors properly without blanket statements. It would be really helpful if an answer does not just tell me how to handle a mkdir exception, but print (or otherwise find the name to) any exception I may run into down the line (mkdir is just an example).
Thank you!
The issue is that fabric uses subprocess for doing these sorts of things. If you look at the source code for local you can see it doesn't actually raise an exception. It calls suprocess.Popen and uses communicate() to read stdout and stderr. If there is a non-zero return code then it returns a call to either warn or abort. The default is abort. So, to do what you want, try this:
def init():
with settings(warn_only=True):
local('mkdir ./www')
If you look at the source for abort, it looks like this:
10 def abort(msg):
21 from fabric.state import output
22 if output.aborts:
23 sys.stderr.write("\nFatal error: %s\n" % str(msg))
24 sys.stderr.write("\nAborting.\n")
25 sys.exit(1)
So, the exception would be a SystemExit exception. While you could catch this, the proper way to do it is outlined above using settings.
It is nothing to handle with exception, it is from the fabric api
try to set the entire script's warn_only setting to be true with
env.warn_only = True
Normally, when you get an uncaught exception, Python will print the exception type along with the error message:
>>> raise IOError("Error message.")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: Error message.
If that's not happening, you're probably not getting an exception at all.
If you really want to catch an arbitrary exception and print it, you want to catch Exception or BaseException. BaseException will include even things like KeyboardInterrupt, though, so be careful with that.
def init():
try:
local('mkdir ./www')
except BaseException as e:
print "local() threw a", type(e).__name__
raise # Reraise the exception
In general:
try:
some_code()
except Exception, e:
print 'Hit An Exception', e
raise
Will tell you what the exception was but if you are not planning on actually handling some of the exceptions then simply getting rid of the try: except: lines will have exactly the same effect.
Also if you run your code under a debugger then you can look at the exception(s) that you hit in more detail.
def init():
try:
local('mkdir ./www')
except Exception as e:
print e.__class__.__name__
That's all there is to it!
edit: Just re-read your question and realized that my code would only print "Fatal" in your case. It looks like fabric is throwing an error and returning their own error code so you would have to look at the documentation. I don't have any experience with fabric so I'd suggest to look here if you haven't already. Sorry if this isn't helpful!

Categories

Resources