If I execute capture_exception(e) from sentry_sdk within the except block as below, all the local variables and their values are included which is useful for debugging.
try:
a=1/0
except:
capture_exception(sys.exc_info())
My application will be offline at times and so I need to pickle my exceptions and periodically retry sending to Sentry from another proces.
I've used tblib for this however it does not serialize sys.exc_info()[2].tb_frame.f_locals.
tblib appears to empty the f_locals attribute and consequently my Sentry exceptions lack this information. I mainly want to see numerical and string values in my sentry exceptions, all of which should be easily pickleable.
I attempted to separately pickle f_locals, skipping any non-picklable values, however I get the error when attempting to write it to the de-pickled traceback:
AttributeError: attribute 'f_locals' of 'frame' objects is not
writable
Is there any simple way to accomplish my goal outside of tblib?
Related
During development using drf, an efficient method for error handling was needed.
I found two methods, one using ErrorResponse created by inheriting Response, and one using APIException provided by drf.
The first method is done through return, and the second method uses the raise command.
I wonder which one is more efficient and why!
I apologize in advance for the question may be too vague.
Not sure if efficiency and CPU time is most important thing.
You have to understand Django request-response cycle first. The next step after return Response (or raise Exception) is not a client side browser but number of Middlewares that you imported in your application. And these Middlewares may be different depends on what happens inside View.
When you raising something you break this cycle flow.
Django handling raised exception, writing extra error logs, returning specified error response to client side. You don't have to care that all conditions of correct responses will be satisfied, because error already happens, it is already not correct. In other way returned Response will be delivered to client side by normal way. Django will care that all validations and steps will be passed before response reach a client.
If you need to save milliseconds by choosing between return / raise and deeply thinking about efficiency, at first stop using Django. Seriously. It is slowest framework even for python.
raise produces an error in the current level of the call stack. You can catch a raised error by covering the area where the error might be raised in a try and handling that error in an except.
return on the other hand, returns a value to where the function was called from, so returning an exception usually is not the functionality you are looking for in a situation like this, since the exception itself is not the thing triggering the except it is instead the raising of the exception that triggers it.
https://docs.python.org/3/reference/simple_stmts.html#raise
https://docs.python.org/3/reference/simple_stmts.html#return
So to answer your question I would raise because it is built for errors compared to return. Also, they are the same in speed/efficiency.
I am using a 3rd party Python package which has low-level C bindings and messes the type checks on my code base whenever I use some of the classes from this package. Probably because some methods are created during run-time so they don't exist during static analysis.
For example, there is a class called Signal which has methods like connect() or emit() but using these methods cause mypy to give hundreds of errors like this although the code is working well:
...
production_test_window.py:192: error: "Signal" has no attribute "connect"
production_test_window.py:193: error: "Signal" has no attribute "connect"
production_test_window.py:194: error: "Signal" has no attribute "connect"
production_test_window.py:195: error: "Signal" has no attribute "connect"
production_test_window.py:247: error: "Signal" has no attribute "connect"
...
As you can see, the errors are happening repeatedly because of the Signal.connect() method, although the connect() method exists (in run-time). Because I am using this method hundreds of times, I don't want to put # type: ignore to each of these lines.
Instead, is there a way to tell mypy to ignore checking method calls of Signal class usages of the 3rd party package I am using?
I've seen some questions that kind of get at what I'm going for, but haven't found anything that quite satisfies my question.
I'm creating a fairly large and complex web server using blueprints in Python Flask. I would like to, when I encounter an error (try... except...), be able to log the error, among other things. Writing the code to log the error and traceback in each exception seems to violate DRY.
I know I could just define a normal method that has inputs for Strings and whatnot, where I could pass in my exception and traceback, but this feels wrong to me for some reason.
So my question is, is there a way to be able to, when something triggers an error, raise another exception while preserving the traceback, where I can have my error handling logic (logging, showing errors to user, etc)?
I'd like my web server code to look like this:
try:
# some error-prone process
except:
raise errorHandler # where "errorHandler" is my custom error handler
Additionally, this project is Python 3, so I would prefer to use something that plays nice with Python 3.
Thanks!
I am writing tests for some legacy code that is littered with catch-all constructs like
try:
do_something()
do_something_else()
for x in some_huge_list():
do_more_things()
except Exception:
pass
and I want to tell whether an exception was thrown inside the try block.
I want to avoid introducing changes into the codebase just to support a few tests and I don't want to make the except cases more specific for fear of unintentionally introducing regressions.
Is there a way of extracting information about exceptions that were raised and subsequently handled from the runtime? Or some function with a similar API to eval/exec/apply/call that either records information on every raised exception, lets the user supply an exception handler that gets run first, or lets the user register a callback that gets run on events like an exception being raised or caught.
If there isn't a way to detect whether an exception was thrown without getting under the (C)Python runtime in a really nasty way, what are some good strategies for testing code with catch-all exceptions inside the units you're testing?
Your only realistic option is to instrument the except handlers.
Python does record exception information, which is retrievable with sys.exc_info(), but this information is cleared when a function exits (Python 2) or the try statement is done (Python 3).
A good strategy would be testing observable behaviour. Since exceptions were explicitly excluded from the observable behaviour I do not think you should be testing whether an exception was raised or not.
How can I wrap a boto.storage_uri() call in python so I can handle possible exceptions?
Your question about Boto is a good one, not not easy to answer. The Boto exception hierarchy is poorly designed, and ultimately the only way to determine what the exception you want to trap is requires looking at the boto source code.
For example if you look at (on Ubuntu) /usr/share/pyshared/boto/exception.py you will see that there are two broad classes:
boto.exception.BotoClientError
boto.exception.BotoServerError
Many of the exceptions are derived from these two, though the concept of "Client" and "Server" is not very well defined and you probably would want to check for both to be sure as many exceptions can happen unexpected (as usual). However, exceptions such as boto.exception.NoAuthHandlerFound is derived directly from Exception and therefore you would have to check for it separately.
Unfortunately from looking at the code, it appears that there is neither consistency nor much care in defining the exception hierarchy in Boto, which is a flaw in Boto's design which unfortunately requires that you rely on more broad exception checking than would normally be recommended.
The first question is what exceptions is this call likely to generate? You do not want to make a blanket exception handler in any language. You should first take a look at the Boto documentation to see if it documents the exceptions you might see from a given call, but if not I would first try:
try:
uri = boto.storage_uri()
except Exception, e:
print e
Or log the exception (with the logging package exception method), but either way you want to take note of what types of exceptions you see while you're testing and whether you should handle any of them specially. You also may want to review the Python Tutorial section on Exceptions and Errors.
Looking at the boto3 source, Boto3Error is declared as the base of all boto errors. So, you can probably do this:
try:
boto.storage_uri()
except Boto3Error:
# handle errors