raise the exception in a try/except and continue - python

so basically I have a loop and for each step, I run a function in a try/except. When there is an error caught, I have a generic error message that doesn't allow me to understand what went wrong.
How do I have the real python built-in error message (raise) and still continue to run the loop?
Thanks.

Sample code:
for i in [...]:
try:
func1(i)
except Exception as ex:
print(ex)
func2(i)

Related

How to print exception errors and trace tacks in a file when there's an error in my code?

I want that whenever an error is raised in my code, traceback.print_exception() execute so I can have any errors in a file to check... Is it possible somehow?
You could try wrapping your code in a try/except block, and call the function in the except. It might look like this:
try:
# Your code here
except Exception as e:
traceback.print_exception(e)

Why asyncio raises TimeoutError without any message?

I encountered a small annoyance with this code:
try:
return await asyncio.wait_for(tcp_command(cmd), timeout=timeout)
except (OSError, asyncio.TimeoutError) as err:
print(f"Network problem: {err}")
When the timeout occurs, it prints just "Network problem: ". It is caused by an empty value attached to the raised asyncio.TimeoutError:
# inside wait_for():
raise futures.TimeoutError()
It is easy to hadle the TimeoutError separately, but I find the original construct quite idiomatic and now a core library breaks it. Is there a good reason for it? Is my assumption - that printing an exception should give us a clue what went wrong - correct?
Is there a good reason for it?
Yes, what kind of message you expect from TimeoutError? "Timeout occured"? The exception itself is self-explanatory, no need for such redundancy.
Is my assumption - that printing an exception should give us a clue what went wrong - correct?
Yes and no. Clue? Yes. Full information? No. The exception message is not mandatory. And the type of an exception is an important piece of information as well. And in many cases even more then the message itself.
So first of all: using print is wrong to begin with. Python has a very rich logging support. For example logger.exception(str(exc)) solves your problem because it logs entire traceback in addition to the message. At least by default, it can be customized.
But if you still want to use print then consider logging whole traceback:
import traceback
# traceback.print_exc()
print(traceback.format_exc())
If whole traceback is too big then you can always simply print the exception's class name:
# print(f'[{type(exc).__name__}] {exc}')
print(f'[{type(exc)}] {exc}')
or customize by exception:
try:
return await asyncio.wait_for(tcp_command(cmd), timeout=timeout)
except OSError as err:
print(f"Network problem: {err}")
except asyncio.TimeoutError:
print('Timeout occured')
The expectation that an exception will provide a message that explains the issue is not part of the general exception contract in Python. It is true for system exceptions such as OSError where the program must be able to get to the error message provided by the operating system, as the program is not qualified to guess the message based on a code or an exception subtype.
But more basic language exceptions do not work like that. Take, for example, KeyError raised by dict.__getitem__:
>>> try:
... d[123]
... except KeyError as err:
... print(f"Dict problem: {err}")
...
Dict problem: 123
In this sense, TimeoutError is much more like KeyError than like OSError. When you catch TimeoutError, you know exactly what happened - a timeout. You typically want to do something based on the fact that a timeout happened, rather than just display a message to the user. And even if you did want to provide a message, you'd use one that would make sense for your application, not a generic one provided by Python. This is in contrast to OSError where you often cannot do anything other than display the message coming from the OS and where that message can prove invaluable for investigating the underlying issue.
To sum it up, the problem is that you are catching two fundamentally different exceptions in the same except clause, and that set you up for trouble. I would restructure the code like this:
try:
return await asyncio.wait_for(tcp_command(cmd), timeout=timeout)
except OSError as err:
print(f"Network problem: {err}")
except asyncio.TimeoutError:
print("Operation timed out")

Create custom exceptions?

Is there a way to shorten the following scenario so i don't have to use an ugly nested try except statement?
class Error(Exception):
def __init__(self):
print("That did not work")
try:
try:
gblgbl
except:
raise Error
except Error:
pass
What i want can be described as following pseudo code:
Try something:
something
if something went wrong:
raise Error
catch Error:
what to do if error occours
I don't want to raise the error if the try statement succeeds, however if i raise an exception in the exception statement like this:
try:
gblgbl
except:
raise Error
except Error:
pass
it can't be caught with an other except, since there is already an except that caught the python exception and the interpreter throws a SyntaxError.
Am i missing something obvious?
I'm aware that you probably would never use this in an actual program, but i'm curious about the theory.
There is no reason to use an exception here. The following (pseudo-)code achieves the same thing.
try:
gblgbl
except:
pass
Note however that it generally is a bad idea to catch all exceptions, since for instance the KeyboardInterrupt Exception will also be caught and the program can thus not be interrupted using Ctrl-c
Create custom exceptions?
The Python Tutorial has a section on User-defined Exceptions

What happens exactly internally when I terminate my Python script using Ctrl+c?

These days I am learning Python's Exception handling features deeply. I encountered exception SystemExit. While reading about this from official Python Docs I got question in mind that what exactly would have happen when I terminate Python script by pressing Ctrl+c?
lets take this sample code:
def func1(a,b):
print "func1: "+str(a/b)
#some more functions
def func2(a,b):
print "func2: "+str(a/b)
#some more functions
if __name__=="__main__":
import random
count=0
for i in range(1000000):
count=count+1
print "count: "+str(count)
try:
func1(random.randint(-2,3),random.randint(-2,3))
except KeyboardInterrupt:
raise
except:
print "error in func1"
try:
func2(random.randint(-2,3),random.randint(-2,3))
except KeyboardInterrupt:
raise
except:
print "error in func2"
print "\n"
In this sample code I am catching KeyboardInterrupt so I can stop my script by pressing Ctrl+c. Should I catch SystemExit too to make this code more mature? if yes then why? actually this question is source of my main question which appear on title. so don't consider that I am asking two different question in one post.
You usually not need to catch SystemExit as it is what makes exit() and sys.exit() functions work:
sys.exit([arg])
Exit from Python. This is implemented by raising the SystemExit exception, so cleanup actions specified by finally clauses of try statements are honored, and it is possible to intercept the exit attempt at an outer level.
Example:
try:
exit()
except SystemExit:
print "caught"
Therefore, you usually don't want to catch all exceptions in the first place (by using an empty except: clause). The best approach is generally to make your exception handlers as specific as possible. It otherwise makes debugging your application exceptionally hard, as it either hides errors entirely or at least makes it hard to diagnose the details.
The only exception your functions can raise is a ZeroDivisionError, so you should only catch that one:
import random
if __name__ == "__main__":
for count in range(1000000):
print "count:", count
try:
func1(random.randint(-2, 3),random.randint(-2, 3))
except ZeroDivisionError:
print "error in func1"
try:
func2(random.randint(-2, 3),random.randint(-2, 3))
except ZeroDivisionError:
print "error in func2"
print "\n"
Your title says something different than the body of your question.
To the title:
What happens internally is that python captures the SIGINT and raises a KeyboardInterrupt exception from it.
To the text:
You don't want to do except:.
Instead, you want
if __name__=="__main__":
try:
import random
count=0
for i in range(1000000):
count=count+1
print "count: "+str(count)
try:
func1(random.randint(-2,3),random.randint(-2,3))
except Exception, e:
print "error in func1", e # or something...
try:
func2(random.randint(-2,3),random.randint(-2,3))
except Exception, e:
print "error in func2", e # or something...
print "\n"
except Exception:
raise # any other "normal" exception.
except: # Here it is ok, as you handle most exceptions above.
pass
Most "normal" exception which should normally be handled derive from Exception. Those which have an internal meaning and should normally not be caught (except on global level) don't derive from Exception.
These are KeyboardInterrupt, SystemExit and GeneratorExit.
If you're uncertain what exceptions the code you're calling throws to indicate errors then you should (in order of preference):
Find out what it is documented to throw and only catch that
catch Exception, not everything.
Neither KeyboardInterrupt nor SystemExit is a subclass of Exception, but all of the standard Python exceptions used to indicate errors are.

Python try except

try:
#statement 1
#statement 2
except Exception, err:
print err
pass
This may be very trivial but I never actually thought about it until now and I found myself not being able to answer the following questions:
Does statement 2 gets executed if an error is raised in statement 1?
How does Exception deal with in a case where an error is raised for both statement 1 and statement 2? Which error does it print out in the above code? Both?
The answer is "no" to both of your questions.
As soon as an error is thrown in a try/except block, the try part is immediately exited:
>>> try:
... 1/0
... print 'hi'
... except ZeroDivisionError, e:
... print 'error'
...
error
>>>
As you can see, the code never gets to the print 'hi' part, even though I made an except for it.
You can read more here.
From Python docs:
If an exception occurs during execution of the try clause, the rest of
the clause is skipped. Then if its type matches the exception named
after the except keyword, the except clause is executed, and then
execution continues after the try statement.
So as soon as an error occurs, it skips to the exception
http://docs.python.org/2/tutorial/errors.html
Upon an exception being raised control leaves the try block at the point the exception is raised and is given to the appropriate except block. If statement 1 throws an exception, statement 2 will not execute.
This answers your second question as well: it's not possible for the scenario you describe to happen.
1) Does statement 2 gets executed if an error is raised in statement 1?
No. Exception will be raised and catched.
As I understand python will move up the stack and looks for an exception handler in the caller
2) How does Exception deal with in a case where an error is raised for both statement 1 and statement 2? Which error does it print out in the above code? both?
statement 2 will not be run so no exceptions will be raised for it
any exception from the try block will be caught. That is why for all try/except clauses, limit the try clause to the absolute minimum amount of code necessary. Again, this avoids masking bugs.
1) Does statement 2 gets executed if an error is raised in statement
1?
nope, statement 2 is not executed
2) How does Exception deal with in a case where an error is raised for
both statement 1 and statement 2? Which error does it print out in the
above code? both?
only statement 1 has a chance to raise an error, see above,
NOTE: if you want statement 2 to execute always, you can use finally with the try/except

Categories

Resources