Python debugging in eclipse stop on outer except block - python

I have nested exceptions handling in my code, when inner blocks do some stuff before re-raising the exception to upper layers.
Traceback always reports the line number that started the exception handling.
However, when running in UI debugger (Pydev/Eclipse) it stops on the outer exception block in some cases.
Consider the following code for example:
import sys
def f(a):
c=5/a
return c
def sub(d):
print("Entered sub(%d)" % d)
try:
print("Entered try #sub")
e = f(d)/(d-1)
return e
except:
print("Do some staff before re-raising the exception upwards")
raise
def main():
try:
print("Entered try #main")
d = int(sys.argv[1])
sub(d)
except:
print("Reached except block #main")
raise
if __name__ == '__main__':
main()
When running with argument = 0, the exception is caused at line#4 and the debugger stops on that line:
However, when running with argument = 1, the exception is caused at line#11 (as reported in the printed traceback) but the debugger stops at line#15.
Once the debugger stops at the incorrect location it is very difficult to watch internal variables and handle the error, especially when the code in the try block uses loops.
In Pydev->Manage Exceptions, I checked only the "suspend on uncaught exceptions".
There is a checkbox "Skip exceptions caught in same function" that seem related (because it seems like the debugger skipped the first exception in sub and stopped on "raise" statement which can be considered another exception in same function, although the documentation says that it should re-raise the same exception).
This checkbox is grayed out unless I first check "Suspend on caught exceptions*", but once enabling it the debugger gets stuck and does not stop anywhere...
Will appreciate your help.
-Moshe

Related

Terminating program from a thread contained in try/except block

can someone help me with terminating this program from if statement. I can't get it done. I've tried to this with sys.quit, but it seems to be not suitable for try/except block and I can't break out of the loop within thread. I could do this in the run() method, but it's a little bit useless to build a thread and then try to do something outside of it. It feels like there is something wrong about it. Here's code:
class TradingBot:
def init(self) -> None:
self.api = tradeapi.REST(key_id=API_KEY, secret_key=SECRET_KEY, base_url=BASE_URL, api_version='v2')
def simple_thread(self):
try:
account = self.api.get_account()
clock = self.api.get_clock()
balance_change = float(account.equity) - float(account.last_equity)
condition_1 = balance_change > 0
condition_2 = balance_change < 0
if condition_1:
pass
#Figure out something to quit if condition 1 is met
elif condition_2:
pass
#Figure out something to quit if condition 2 is met
except:
print('Some error has occured')
def run(self):
while True:
execute = threading.Thread(target=self.simple_thread())
execute.start()
time.sleep(1)
sys.exit attempts to exit by throwing a SystemExit exception, which is caught by the bare except clause. I'm not sure why you need the try/except at all, but you should probably at least change it to catch only Exception, which, unlike BaseException, only includes normal exceptions, not special ones such as SystemExit.

Code stops and reports no exceptions (using "requests")

I'm new to Python. I tried to recreate the "Timer" control used in .NET Framework ("Timer" in Python is a different thing...). So, basically, I created a function named CheckMessages that, after its execution, stops the main thread for 1 second and then calls again CheckMessages. Under normal circumstances (=when no exception in the code is thrown), this works good. The timing between one execution and the next is obviously not precise (it is never 1 second) but for the scope of my app this is not a problem.
The problem is: when an exception is thrown, nothing happens. The code does not follow my try ... except logic (no logs are shown) and the app does not exit.
import time
import sched
import requests
s = sched.scheduler(time.time, time.sleep)
def CheckMessages(sc):
newMsgsReq = ""
try:
newMsgsReq = requests.get("...")
except requests.HTTPError as errh:
print ("Http Error:",errh)
except requests.ConnectionError as errc:
print ("Connection Error:",errc)
except requests.Timeout as errt:
print ("Timeout Error:",errt)
except requests.RequestException as err:
print ("OOps: Something Else",err)
msgInf = newMsgsReq.text.split("|")
#...
s.enter(1, 1, CheckMessages, (sc,))
s.enter(1, 1, CheckMessages, (s,))
s.run()
When, for example, I disable my internet connection, I would expect my app to report: Connection Error:... (line 11 of the code snippet). Instead, as said, nothing happens. The app remains active but the output is empty. The function CheckMessages stops being executed every 1 sec.
When I put in an invalid URL ("http://sdkls9e9i.ooo"), I see the exception printed successfully.
After an exception from requests is handled, the script quits with AttributeError: 'str' object has no attribute 'text' because you attempt to work with the response (msgInf = newMsgsReq.text.split("|")) after you've handled an exception.
When I followed your lead and disabled my internet connection, the script indeed "hang". Hitting CTRL+C revealed that it was waiting in:
File ".../site-packages/urllib3/util/connection.py", line 70, in create_connection
sock.connect(sa)
After I added a timeout: requests.get("...", timeout=1), I got the exception as well.
P.S. note that PEP 8 style guide recommends using lower_case_with_underscore for variable and function names.

GeneratorExit, close() does not cause a traceback/exception - how?

def receiver():
print("Ready to receive")
# try:
while True:
n = (yield)
print("Got %s" % n)
# except GeneratorExit:
# print("Receiver done")
r = receiver()
r.next()
r.send(10)
r.close()
When I comment out the GeneratorExit, the close() does not generate traceback! Why? However with the except active, i'm able to catch the GeneratorExit. How is that possible?
If GeneratorExit is an exception, then it should behave like all other exceptions and propagate out which it is doing - hence my ability to catch it using an except. But then surely without the except the parent python interpreter should catch the traceback like what happens with all other exceptions. What magic's going on here?
See generator.close() documentation.
It is stated that StopIteration and GeneratorExit exceptions are used internally to dictate how the generator exits, and thus are the only exceptions that are not propagated to the caller.
So if you want to re-raise a GeneratorExit exception, you probably have to catch it and encapsulate it in another custom exception.

Break statement in finally block swallows exception

Consider:
def raiseMe( text="Test error" ):
raise Exception( text )
def break_in_finally_test():
for i in range(5):
if i==2:
try:
raiseMe()
except:
raise
else:
print "succeeded!"
finally:
print "testing this!"
break
if __name__=='__main__':
break_in_finally_test()
I expected to see Exception( "Test error" ) to be raised, but instead only "testing this" is printed. The intention, of course, was to call raiseMe() only once, no matter if we succeed or not - but if it raises an exception, I would have wanted to see that!
Why does break swallow the exception that I explicitly raise?
From https://docs.python.org/2.7/reference/compound_stmts.html#finally:
If finally is present, it specifies a ‘cleanup’ handler. The try clause is executed, including any except and else clauses. If an exception occurs in any of the clauses and is not handled, the exception is temporarily saved. The finally clause is executed. If there is a saved exception, it is re-raised at the end of the finally clause. If the finally clause raises another exception or executes a return or break statement, the saved exception is discarded
This also reflects the behaviour expected from the try...finally statement before PEP341:
This is how a try except finally block looked like pre PEP341:
try:
try:
raiseMe()
except:
raise
finally:
#here is where cleanup is supposed to happen before raising error
break
#after finally code: raise error
As the raising of errors never happens in the finally block it is never actually raised.
To maintain backwards compatibility with Python<=2.4, it had to be done in this way.
From the docs Error Handling Docs:
A finally clause is always executed before leaving the try statement, whether an exception has occurred or not.
Your exception never gets raised because you break before the try statement gets fully evaluated.
I think upon reflection that it is due to the fact that break actually raises a StopIteration to "break" out of the for-loop. This is really not very intuitive and not particularly well documented (not mentioned on 1, for example). Could maybe someone confirm/explain it better?
Have the following code structure:
def func():
try:
driver.do("something")
except TimeoutException:
pass
finally:
result = driver.do("something else")
return result
Got the exception by pylint:
return statement in finally block may swallow exception (lost-exception)
Solution was to put return out of the finally statement:
def func():
try:
driver.do("something")
except TimeoutException:
pass
finally:
result = driver.do("something else")
return result # <<

How can I register a function to be called only on *successful* exit of my Python program?

I want to run a task when my Python program finishes, but only if it finishes successfully. As far as I know, using the atexit module means that my registered function will always be run at program termination, regardless of success. Is there a similar functionality to register a function so that it runs only on successful exit? Alternatively, is there a way for my exit function to detect whether the exit was normal or exceptional?
Here is some code that demonstrates the problem. It will print that the program succeeded, even when it has failed.
import atexit
def myexitfunc():
print "Program succeeded!"
atexit.register(myexitfunc)
raise Exception("Program failed!")
Output:
$ python atexittest.py
Traceback (most recent call last):
File "atexittest.py", line 8, in <module>
raise Exception("Program failed!")
Exception: Program failed!
Program succeeded!
Out of the box, atexit is not quite suited for what you want to do: it's primarily used for resource cleanup at the very last moment, as things are shutting down and exiting. By analogy, it's the "finally" of a try/except, whereas what you want is the "else" of a try/except.
The simplest way I can think of is continuing to create a global flag which you set only when your script "succeeds"... and then have all the functions you attach to atexit check that flag, and do nothing unless it's been set.
Eg:
_success = False
def atsuccess(func, *args, **kwds):
def wrapper():
if _success:
func(*args,**kwds)
atexit(wrapper)
def set_success():
global _success
_success = True
# then call atsuccess() to attach your callbacks,
# and call set_success() before your script returns
One limitation is if you have any code which calls sys.exit(0) before setting the success flag. Such code should (probably) be refactored to return to the main function first, so that you call set_success and sys.exit in only one place. Failing that, you'll need add something like the following wrapper around the main entry point in your script:
try:
main()
except SystemExit, err:
if err.code == 0:
set_success()
raise
Wrap the body of your program in a with statement and define a corresponding context object that only performs your action when no exceptions have been raised. Something like:
class AtExit(object):
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_value is None:
print "Success!"
else:
print "Failure!"
if __name__ == "__main__":
with AtExit():
print "Running"
# raise Exception("Error")

Categories