How to print python exception thrown inside exec() function from outside - python

I am writing a little software for executing python codes and I want to print exceptions. The following function gets executed:
def run(self, mode='activate'):
try:
exec(self.mycode)
except Exception:
print(traceback.format_exc())
There is no information about what exactly will be executed in the exec() function, it can literally be any python code. I want to print an exception thrown (mostly automatically by python due to code errors) somehow like shown, while executing via exec() including the line of code passed into the exec() function where the exception has been thrown.
I so far only managed to get the 'exec(mycode)' as exception code output, but I want the actual line of code that crashed in mycode.

try this :
def run(self, mode='activate'):
try:
exec(your_code)
except Exception as e:
print(e)
This would work!

add this line traceback.print_exc()
def run(self, mode='activate'):
try:
exec(your_code)
except Exception as e:
print(e)
traceback.print_exc()
This would give you the exception information and also will give you line number where the exception/error occurred!

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.

How to get result from os.execvp() in python 2.7?

I am using os.execvp() function in python. I am not able to get result of this function.
try:
msi_install_cmd = ['msiexec.exe', '/quiet', '/i ', msi_path.encode('mbcs')]
os.execvp(msi_install_cmd[0], msi_install_cmd)
except Exception, error:
raise Exception("MSI installed failed")
Problem is not able to get return-code or exception from os.execvp().
os.exec*() and friends don't return by design. exec() replaces the current process with the one invoked. You could think of calling exec() as "stop doing my program here and continue with this program".
If you want the return code from a (child) process, the subprocess module is a better match:
try:
msi_install_cmd = ['msiexec.exe', '/quiet', '/i ', msi_path.encode('mbcs')]
subprocess.check_call(msi_install_cmd)
except Exception as error:
raise Exception("MSI installed failed: {}".format(error.message))

Catching an exceptions in __enter__ in the calling code in Python

Is there a way I can catch exceptions in the __enter__ method of a context manager without wrapping the whole with block inside a try?
class TstContx(object):
def __enter__(self):
raise Exception("I'd like to catch this exception")
def __exit__(self, e_typ, e_val, trcbak):
pass
with TstContx():
raise Exception("I don't want to catch this exception")
pass
I know that I can catch the exception within __enter__() itself, but can I access that error from the function that contains the with statement?
On the surface the question Catching exception in context manager __enter__() seems to be the same thing but that question is actually about making sure that __exit__ gets called, not with treating the __enter__ code differently from the block that the with statement encloses.
...evidently the motivation should be clearer. The with statement is setting up some logging for a fully automated process. If the program fails before the logging is set up, then I can't rely on the logging to notify me, so I have to do something special. And I'd rather achieve the effect without having to add more indentation, like this:
try:
with TstContx():
try:
print "Do something"
except Exception:
print "Here's where I would handle exception generated within the body of the with statement"
except Exception:
print "Here's where I'd handle an exception that occurs in __enter__ (and I suppose also __exit__)"
Another downside to using two try blocks is that the code that handles the exception in __enter__ comes after the code that handles exception in the subsequent body of the with block.
You can catch the exception using try/except inside of __enter__, then save the exception instance as an instance variable of the TstContx class, allowing you to access it inside of the with block:
class TstContx(object):
def __enter__(self):
self.exc = None
try:
raise Exception("I'd like to catch this exception")
except Exception as e:
self.exc = e
return self
def __exit__(self, e_typ, e_val, trcbak):
pass
with TstContx() as tst:
if tst.exc:
print("We caught an exception: '%s'" % tst.exc)
raise Exception("I don't want to catch this exception")
Output:
We caught an exception: 'I'd like to catch this exception'.
Traceback (most recent call last):
File "./torn.py", line 20, in <module>
raise Exception("I don't want to catch this exception")
Exception: I don't want to catch this exception
Not sure why you'd want to do this, though....
You can use contextlib.ExitStack as outlined in this doc example in order to check for __enter__ errors separately:
from contextlib import ExitStack
stack = ExitStack()
try:
stack.enter_context(TstContx())
except Exception: # `__enter__` produced an exception.
pass
else:
with stack:
... # Here goes the body of the `with`.

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!

Catch any error in Python [duplicate]

This question already has answers here:
How can I write a `try`/`except` block that catches all exceptions?
(10 answers)
Closed 1 year ago.
Is it possible to catch any error in Python? I don't care what the specific exceptions will be, because all of them will have the same fallback.
Using except by itself will catch any exception short of a segfault.
try:
something()
except:
fallback()
You might want to handle KeyboardInterrupt separately in case you need to use it to exit your script:
try:
something()
except KeyboardInterrupt:
return
except:
fallback()
There's a nice list of basic exceptions you can catch here. I also quite like the traceback module for retrieving a call stack from the exception. Try traceback.format_exc() or traceback.print_exc() in an exception handler.
try:
# do something
except Exception, e:
# handle it
For Python 3.x:
try:
# do something
except Exception as e:
# handle it
You might want also to look at sys.excepthook:
When an exception is raised and uncaught, the interpreter calls
sys.excepthook with three arguments, the exception class, exception
instance, and a traceback object. In an interactive session this
happens just before control is returned to the prompt; in a Python
program this happens just before the program exits. The handling of
such top-level exceptions can be customized by assigning another
three-argument function to sys.excepthook.
Example:
def except_hook(type, value, tback):
# manage unhandled exception here
sys.__excepthook__(type, value, tback) # then call the default handler
sys.excepthook = except_hook
Quoting the bounty text:
I want to be able to capture ANY exception even weird ones like
keyboard interrupt or even system exit (e.g. if my HPC manger throws
an error) and get a handle to the exception object e, whatever it
might be. I want to process e and custom print it or even send it by
email
Look at the exception hierarchy, you need to catch BaseException:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
This will capture KeyboardInterrupt, SystemExit, and GeneratorExit, which all inherit from BaseException but not from Exception, e.g.
try:
raise SystemExit
except BaseException as e:
print(e.with_traceback)
Not mentioning the type of exception you want to handle itself does the job.
Try this:
try:
#code in which you expect an exception
except:
#prints the exception occured
if you want to know the type of exception that occurred:
try:
# code in which you expect an exception
except Exception as e:
print(e)
# for any exception to be catched
print(type(e))
# to know the type of exception.
for detailed explanation go trough this
https://www.tutorialspoint.com/python/python_exceptions.htm
# in python 3
# if you want the error
try:
func()
except Exception as e:
exceptionFunc(e)
# if you simply want to know an error occurs
try:
func()
except:
exceptionFunc()
# if you don't even wanna do anything
try:
func()
except:
pass
The following only worked for me (both in PY2 and PY3):
try:
# (Anything that produces any kind of error)
except:
ertype = sys.exc_info()[0] # E.g. <class 'PermissionError'>
description = sys.exc_info()[1] # E.g. [Errno 13] Permission denied: ...
# (Handle as needed )
Built-In Exceptions in Python
Built-In exception classes are divided into Base error classes from which the error classes are defined and Concrete error classes which define exceptions which you are more likely to see time to time.
The more detailed document about the buit-In exception can be found in [https://docs.python.org/3/library/exceptions.html]
Custom Exceptions
It is used to fit your specific application situation. For example, you can create your own exception as RecipeNotValidError as the recipe is not valid in your class for developing a cooking app.
Implementation
class RecipeNotValidError(Exception):
def __init__(self):
self.message = "Your recipe is not valid"
try:
raise RecipeNotValidError
except RecipeNotValidError as e:
print(e.message)
These are custom exceptions that are not defined in the standard library. The steps you can follow to create custom classes are :
Subclass the Exception class.
Create a new Exception class of your choice.
Write your code and use the try...except flow to capture and handle your custom exception.

Categories

Resources