I have a program that exposes different API, some of them require a huge amount of time.
Sometimes it happens that an user insert wrong data in the algorithm and has to abort the execution.
I'm trying to create that system raising a keyboardException and catching from another API, but actually without any result.
Can someone please address me ? Below my test code
#ns.route('/abort')
class ProjectItem(Resource):
def get(self):
raise KeyboardInterrupt
return None,200
#ns.route('/test')
class ProjectItem(Resource):
def get(self):
try:
print('start')
time.sleep(5)
print('end')
return None,400
except KeyboardInterrupt:
print("interrupted, yay!")
return None,200
I have even tryed this way
#ns.route('/abort')
class ProjectItem(Resource):
def get(self):
print('abort')
sys.exit("pls pls pls")
print('aborting')
return None,200
#ns.route('/test')
class ProjectItem(Resource):
def get(self):
try:
print('start')
time.sleep(5)
print('end')
return None,400
except:
print("interrupted, yay!")
return None,200
but still unable to see that agognated "yay"
Related
I'm trying to use playwright with my smoke ui test. When i add the function in the page object class, i always write the case as following:
#allure.step("click the Next button")
def saveAndNext(self):
try:
self.nextBtn.click()
except Exception as e:
allure.attach(str(e), name="Exception", attachment_type=allure.attachment_type.TEXT)
raise AssertionError(f"【{sys._getframe().f_code.co_name}】 Step Failure")
finally:
self.saveImage()
however, i want to add a decorate to save my code with the try-catch-finally struct as the following:
def test_deco(page)
def error_catch(func):
def trycatch(*args, **kwargs):
try:
return func(page)
except Exception as e:
allure.attach(str(e), name="Exception", attachment_type=allure.attachment_type.TEXT)
raise AssertionError(f"【{sys._getframe().f_code.co_name}】 Step Failure")
finally:
page.saveImage()
pass
return trycatch()
return error_catch()
But it does not works, since i can not use this deco with pass the "self.page" param, which would throw the error.
#test_deco(self.page)
#allure.step("xx")
def saveAndNext(self):
self.nextBtn.click()
How could i do if i want to achieve this function to save my time. Any comments is appreciate~~
I am working with a class in python that is part of a bigger program. The class is calling different methods.
If there is an error in one of the method I would like code to keep running after, but after the program is finished, I want to be able to see which methods had potential errors in them.
Below is roughly how I am structuring it at the moment, and this solution doesn't scale very well with more methods. Is there a better way to provide feedback (after the code has been fully run) as to which of the method had a potential error?
class Class():
def __init__(self):
try:
self.method_1()
except:
self.error_method1 = "Yes"
break
try:
self.method_2()
except:
self.error_method2 = "Yes"
break
try:
self.method_3()
except:
self.error_method3 = "Yes"
break
Although you could use sys.exc_info() to retrieve information about an Exception when one occurs as I mentioned in a comment, doing so may not be required since Python's standard try/expect mechanism seems adequate.
Below is a runnable example showing how to do so in order to provide "feedback" later about the execution of several methods of a class. This approach uses a decorator function, so should scale well since the same decorator can be applied to as many of the class' methods as desired.
from contextlib import contextmanager
from functools import wraps
import sys
from textwrap import indent
def provide_feedback(method):
""" Decorator to trap exceptions and add messages to feedback. """
#wraps(method)
def wrapped_method(self, *args, **kwargs):
try:
return method(self, *args, **kwargs)
except Exception as exc:
self._feedback.append(
'{!r} exception occurred in {}()'.format(exc, method.__qualname__))
return wrapped_method
class Class():
def __init__(self):
with self.feedback():
self.method_1()
self.method_2()
self.method_3()
#contextmanager
def feedback(self):
self._feedback = []
try:
yield
finally:
# Example of what could be done with any exception messages.
# They could instead be appended to some higher-level container.
if self._feedback:
print('Feedback:')
print(indent('\n'.join(self._feedback), ' '))
#provide_feedback
def method_1(self):
raise RuntimeError('bogus')
#provide_feedback
def method_2(self):
pass
#provide_feedback
def method_3(self):
raise StopIteration('Not enough foobar to go around')
inst = Class()
Output:
Feedback:
RuntimeError('bogus') exception occurred in Class.method_1()
StopIteration('Not enough foobar to go around') exception occurred in Class.method_3()
I have a script executing several independent functions in turn. I would like to collect the errors/exceptions happening along the way, in order to send an email with a summary of the errors.
What is the best way to raise these errors/exceptions and collect them, while allowing the script to complete and go through all the steps? They are independent, so it does not matter if one crashes. The remaining ones can still run.
def step_1():
# Code that can raise errors/exceptions
def step_2():
# Code that can raise errors/exceptions
def step_3():
# Code that can raise errors/exceptions
def main():
step_1()
step_2()
step_3()
send_email_with_collected_errors()
if '__name__' == '__main__':
main()
Should I wrap each step in a try..except block in the main() function? Should I use a decorator on each step function, in addition to an error collector?
You could wrap each function in try/except, usually better for small simple scripts.
def step_1():
# Code that can raise errors/exceptions
def step_2():
# Code that can raise errors/exceptions
def step_3():
# Code that can raise errors/exceptions
def main():
try:
step_1_result = step_1()
log.info('Result of step_1 was {}'.format(result))
except Exception as e:
log.error('Exception raised. {}'.format(e))
step_1_result = e
continue
try:
step_2_result = step_2()
log.info('Result of step_2 was {}'.format(result))
except Exception as e:
log.error('Exception raised. {}'.format(e))
step_2_result = e
continue
try:
step_3_result = step_3()
log.info('Result of step_3 was {}'.format(result))
except Exception as e:
log.error('Exception raised. {}'.format(e))
step_3_result = e
continue
send_email_with_collected_errors(
step_1_result,
step_2_result,
step_3_result
)
if '__name__' == '__main__':
main()
For something more elaborate you could use a decorator that'd construct a list of errors/exceptions caught. For example
class ErrorIgnore(object):
def __init__(self, errors, errorreturn=None, errorcall=None):
self.errors = errors
self.errorreturn = errorreturn
self.errorcall = errorcall
def __call__(self, function):
def returnfunction(*args, **kwargs):
try:
return function(*args, **kwargs)
except Exception as E:
if type(E) not in self.errors:
raise E
if self.errorcall is not None:
self.errorcall(E, *args, **kwargs)
return self.errorreturn
return returnfunction
Then you could use it like this:
exceptions = []
def errorcall(E, *args):
print 'Exception raised {}'.format(E)
exceptions.append(E)
#ErrorIgnore(errors=[ZeroDivisionError, ValueError], errorreturn=None, errorcall=errorcall)
def step_1():
# Code that can raise errors/exceptions
...
def main():
step_1()
step_2()
step_3()
send_email_with_collected_errors(exceptions)
if '__name__' == '__main__':
main()
use simple try except statements and do logging for the exceptions that would be standard way to collect all your errors.
There are two options:
Use decorator in which you catch all exceptions and save it somewhere.
Add try/except everywhere.
Using decorator might be much better and cleaner, and code will be easier to maintain.
How to store errors? Your decision. You can add them to some list, create logging class receiving exceptions and get them after everything is done… Depends on your project and size of code.
Simple logging class:
class LoggingClass(object):
def __init__(self):
self.exceptions = []
def add_exception(self, exception):
self.exceptions.append(exception)
def get_all(self):
return self.exceptions
Create instance of class in your script, catch exceptions in decorator and add them to class (however global variable might be also ok).
I have a requirement to execute multiple Python statements and few of them might fail during execution, even after failing I want the rest of them to be executed.
Currently, I am doing:
try:
wx.StaticBox.Destroy()
wx.CheckBox.Disable()
wx.RadioButton.Enable()
except:
pass
If any one of the statements fails, except will get executed and program exits. But what I need is even though it is failed it should run all three statements.
How can I do this in Python?
Use a for loop over the methods you wish to call, eg:
for f in (wx.StaticBox.Destroy, wx.CheckBox.Disable, wx.RadioButton.Enable):
try:
f()
except Exception:
pass
Note that we're using except Exception here - that's generally much more likely what you want than a bare except.
If an exception occurs during a try block, the rest of the block is skipped. You should use three separate try clauses for your three separate statements.
Added in response to comment:
Since you apparently want to handle many statements, you could use a wrapper method to check for exceptions:
def mytry(functionname):
try:
functionname()
except Exception:
pass
Then call the method with the name of your function as input:
mytry(wx.StaticBox.Destroy)
I would recommend creating a context manager class that suppress any exception and the exceptions to be logged.
Please look at the code below. Would encourage any improvement to it.
import sys
class catch_exception:
def __init__(self, raising=True):
self.raising = raising
def __enter__(self):
pass
def __exit__(self, type, value, traceback):
if issubclass(type, Exception):
self.raising = False
print ("Type: ", type, " Log me to error log file")
return not self.raising
def staticBox_destroy():
print("staticBox_destroy")
raise TypeError("Passing through")
def checkbox_disable():
print("checkbox_disable")
raise ValueError("Passing through")
def radioButton_enable():
print("radioButton_enable")
raise ValueError("Passing through")
if __name__ == "__main__":
with catch_exception() as cm:
staticBox_destroy()
with catch_exception() as cm:
checkbox_disable()
with catch_exception() as cm:
radioButton_enable()
I'm trying to switch MongoEngine with MotorEngine in my Tornado app for the sake of asynchronous DB access and so far I got nowhere.
query
#gen.coroutine
def get_all_users(self):
users = yield User.objects.find_all()
handler
class IUser(BaseHandler):
#asynchronous
#gen.engine
def get(self,userId=None, *args, **kwargs):
try:
userMethods = UserMethods()
sessionId = self.request.headers.get('sessionId')
ret = userMethods.get_all_users()
except Exception as ex:
print str(ex)
self.finish()
When I print ret variable it says <tornado.concurrent.Future object at 0x7fb0236fe450>. If I try to print ret.result() it gets me nowhere.
Any help is appreciated since I'm struggling with everything I guess...
get_all_users needs to return its value somehow. In Python 2.6 or 2.7, generators aren't allowed to use the "return" statement, so coroutines have a special "Return" exception:
#gen.coroutine
def get_all_users(self):
users = yield User.objects.find_all()
raise gen.Return(users)
In Python 3.3 and later, you can simply "return users".
Now in "get", calling "get_all_users" only gives you a pending Future, not a value. You must wait for the Future to resolve to a value by yielding it:
ret = yield userMethods.get_all_users()
For more about calling coroutines from coroutines, see my "Refactoring Tornado Coroutines".
By the way, you can decorate "get" with just "gen.coroutine", it's more modern than "asynchronous" and "gen.engine", but either style works.
Just a suggestion. If you want to avoid to create an instance of userMethods every time you use its method:
userMethods = UserMethods()
You can use the #classmethod decorator before declaring it:
class UserMethods():
pass
#classmethod
#tornado.gen.coroutine
def get_all_users(self):
users = yield User.objects.find_all()
raise gen.Return(users)
## class IUser
...
try:
# userMethods = UserMethods() --not necesary now--
sessionId = self.request.headers.get('sessionId')
ret = yield userMethods.get_all_users()
except Exception as ex:
print str(ex)
...