I have some code I want to execute if an exception is not thrown.
Currently I'm doing this:
try:
return type, self.message_handlers[type](self, length - 1)
finally:
if not any(self.exc_info()):
self.last_recv_time = time.time()
Can this be improved on? Is this the best way to do it?
Update0
The optional else clause is executed if and when control flows off the
end of the try clause.
Currently, control “flows off the end” except in the case of an
exception or the execution of a return, continue, or break statement.
try:
tmp = type, self.message_handlers[type](self, length - 1)
except Exception:
pass #or handle error, or just "raise" to re-raise
else:
self.last_recv_time = time.time()
return tmp
Your code suggests that you don't want to catch the exception if it occurs, so why not simply
result = type, self.message_handlers[type](self, length - 1)
self.last_recv_time = time.time()
return result
(Am I missing anything?)
Related
I have some code inside a try block that throws a ValueError. I have an except block that catches this ValueError and handles it. Once this is done I do not want other except blocks to catch this ValueError.
In the code below, there is another try except block later in the code and this ValueError is being caught by the second except too. How can I make sure the ValueError is caught only by the first except and not the second one?
# Get features to plot
try: #First Try Block
raw_features_list_1 = fsobject_1.genFeature(gmm.FftClassifier.fft_features)
except ValueError: #First Except Block
pass
filtered_features_list_1 = np.array([row[0] for row in raw_features_list_1 if row is not None]).reshape(-1, 1)
try: #Second Try Block
raw_features_list_2 = fsobject_2.genFeature(gmm.FftClassifier.fft_features)
except ValueError: #Second Except Block
pass
print("I am here")
filtered_features_list_2 = np.array([row[0] for row in raw_features_list_2 if row is not None]).reshape(-1, 1)
The above code gives me the following result:
I am here
NameError Traceback (most recent call last)
<ipython-input-16-ff0067cb5362> in <module>
11 pass
12 print("I am here")
---> 13 filtered_features_list_2 = np.array([row[0] for row in raw_features_list_2 if row is not None]).reshape(-1, 1)
NameError: name 'raw_features_list_2' is not defined
This is because due to the ValueError generated by the first Try Block the second try block is not being evaluated and the the second Except block is being evaluated directly.
I would like to evaluate the first Try Blocks, handle the ValueError in the First Except Block. Then evaluate the second Try Blocks and, if it generates a ValueError, handle that in the second Except Block.
Sorry looks like what I am asking is already the default behavior of python.
I had another issue where the function generating raw_features_list_2 was throwing a ValueError and aborting before returning raw_features_list_2. So I felt as if the second try block wasn't being evaluated at all. I fixed my problem by handling the exception inside the function that returns raw_features_list_2.
As can be seen below, python catches an exception only once.
In [26]: try:
...: 1/0
...: except ZeroDivisionError:
...: print("Caught")
...: try:
...: pass
...: except ZeroDivisionError:
...: print("Caught Again")
Caught
So my question is..kind of irrelevant.
I am repeating a sequence of experiments (with random initialization) like this in Python:
num_rounds = 1e3
result_list = []
for i in range(num_rounds):
result = run_experiment() # with random initialization inside the call of `run_experiment`
result_list.append(result)
However, my code can be buggy and exceptions might be thrown halfway, which will then interrupt the whole loop.
I'm wondering if there a way to:
let go the exception and continue the loop
meanwhile, store the condition (input parameters) that causes the exception(s) somewhere
gather basic statistics of different exceptions, for example the frequency of each exception type.
Or is there already a tool to do that?
1) Let go exception and continue loop:
try:
<whatever code can cause exception>
except <Exceptions you want to catch>:
pass
that will catch the exception and let it slip. Alternatively you can put a continue in the except block:
try:
<whatever code can cause exception>
except <Exceptions you want to catch>:
pass
2) and 3) With the code from 1. you can collect any data you want in the except block and then do a continue:
statistics_list = []
for <something>:
try:
<whatever code can cause exception>
except <Exceptions you want to catch>:
statistics_list.append((exception_type, input params....))
continue
after your loop you can process the data in your statistics list to your liking
There is try..except..else:
num_rounds = 1e3
result_list = []
exceptions = {}
for i in range(num_rounds):
values = 1,2,3, ... # with random initialization outside the call of `run_experiment`
try:
result = run_experiment(*values)
except Exception as e:
exceptions[values] = e
else:
result_list.append(result)
I think you will be able to do your statistics if modify your code like this
num_rounds = 1e3
result_list = []
for i in range(num_rounds):
try:
result = run_experiment()
result_list.append(result)
except Exception as ex:
# do statistics
That way you have the exception as ex, you can check and store the type.
If you also want to store the random input parameters than you should put the same try-except in your run_experiment function
Can you suggest for me a nice way to return to the client if the following function succeeds or not before the timeout is reached?
def until_true(func, condition, timeout):
s = 0.05
t = 0
while t <= timeout:
result = func()
if condition(result):
return t, result
time.sleep(s)
t = t + s
return result
With the current implementation you can test if it has failed by checking the len of the return value which is really ugly. If the function succeeds, I also wish to return the result and the time it took for the function to succeed. If it fails, I wish to return just the result.
Have your first return value as a sentinel to check if it is successful or not. That is
return (True, t, result)
And while accepting it at the calling side have it as success, others, others2 = until_true(..) so that you can test, if success ...
Similarly for the failed portion you can have
return (False, result)
A more pythonic way would be to use exceptions:
class TimeoutException(Exception):
def __init__(self, result):
self.result = result
def until_true(func, condition, timeout):
[...]
raise TimeoutException(result)
try:
time_spent, result = until_true([...])
except TimeoutException as exc:
result = exc.result
The typical pythonic way of reporting error conditions in python is via exceptions rather than return values. In this case you still want to return something, though, so the solution becomes a bit less clear cut. Still, you might want to go with something like this (not tested):
class Timeout(Exception): pass
def until_true(func, condition=bool, timeout=1.0, interval=0.05):
t = 0
while t <= timeout:
result = func()
if condition(result):
return t, result
time.sleep(interval)
t += interval
raise Timeout(result)
try:
t, result = until_true(func)
except Timeout as err:
print "Oh no, timed out! But got result " + str(err.message)
I think this approach is better if timeouts usually shouldn't happen, and require some special action. Otherwise, a simple approach is to simply return t, result in any case, letting the caller check if t is greater than the timeout, or returning some special value for t upon timeout, or even using a third return value like the other answer.
(By the way, your logic assumes that func or condition take no time to execute. If they are time-consuming, until_true will end up running for longer than your timeout since you only count the time spent sleeping. A better approach would use time.time() or similar to check the actual elapsed time.)
If you do a try in python, and the code doesn't fail, but it's outside of a range you want or something, what is the best way to make it fail so it goes to the except?
A simple example is as follows, to check the input is a number between 0 and 1:
input = 0.2
try:
if 0 < float( input ) < 1:
print "Valid input"
else:
"fail"+0 (to make the code go to except)
except:
print "Invalid input"
Is there a better way to go about this? The between range is just an example, so it should work with other things too (also, in the above example, it should also be able to use a number in string format, so detecting the type wouldn't really work).
Sorry but rchang's answer is not reliable for production code (assert statements are skipped if Python is run with the -O flag). The correct solution is to raise a ValueError, ie:
try:
if 0 < float(input) < 1:
raise ValueError("invalid input value")
print "Valid input"
except (TypeError, ValueError):
print "Invalid input"
You can use the raise statement:
try:
if (some condition):
Exception
except:
...
Note that Exception can be more specific, like for example, a ValueError, or maybe it can be an exception defined by you:
class MyException(Exception):
pass
try:
if (some condition):
raise MyException
except MyException:
...
The other answer is accurate. But to educate you more about exception handling ... you could use raise.
Also consider Bruno's comment where he says:
You also want to catch TypeError in case input is neither a string nor a number.
Thus in this case we may add another except block
input = 1.2
try:
if 0 < float( input ) < 1:
print "Valid input"
else:
raise ValueError #(to make the code go to except)
except ValueError:
print "Input Out of Range"
except TypeError:
print "Input NaN"
TypeError will be raised iff the input is an object ( for e.g)
The built-in assertion mechanism may be a fit here.
input = 0.2
try:
assert 0 < float( input ) < 1
print "Valid input"
except (AssertionError, ValueError):
print "Invalid input"
AssertionError will be raised if the condition you provide to the assert statement does not evaluate to True. Also, upon attempting the float conversion upon an invalid value would raise the ValueError.
I'm trying to just execute this simple exceptiion handler and it won't work for some reason. I want it to throw the exception and write the error to a file.
fileo = "C:/Users/bgbesase/Documents/Brent/ParsePractice/out.txt"
g = 4
h = 6
try:
if g > h:
print 'Hey'
except Exception as e:
f = open(fileo, 'w')
f.truncate()
f.write(e)
f.close()
print e
Any ideas what I am doing wrong?
Your snippet is not supposed to raise any exceptions. Maybe you want to do something like
try:
if g > h:
print 'Hey'
else:
raise NotImplementedError('This condition is not handled here!')
except Exception as e:
# ...
Another possibility is that you meant to say:
try:
assert g > h
print 'Hey!'
except AssertionError as e:
# ...
The assert keyword basically behaves like a "fail-safe." If the condition is false, it will raise an AssertionError exception. It is often used to check preconditions for arguments to functions. (Say a value needs to be greater than zero for the function to make sense.)
Edit:
An exception is a sort of "signal" in your code that halts whatever your program was doing and finds it way to the nearest "exception handler." Whenever an exception occurs in your program, all execution immediately halts, and it tries to go to the nearest except: section of the code. If none exists, the program crashes. Try executing the following program:
print 'Hello. I will try doing a sum now.'
sum = 3 + 5
print 'This is the sum: ' + str(sum)
print 'Now I will do a division!'
quotient = 5/0
print 'This is the result of that: ' + str(quotient)
If you run it, you will see that your program crashes. My Python tells me:
ZeroDivisionError: integer division or modulo by zero
This is an exception! Something exceptional happened! You can't divide by zero, of course. As you now know, this exception is a sort of signal that finds its way to the closest exception: block, or the exception handler. We can rewrite this program so it is safer.
try:
print 'Hello. I will try doing a sum now.'
sum = 3 + 5
print 'This is the sum: ' + str(sum)
print 'Now I will do a division!'
quotient = 5/0
print 'This is the result of that: ' + str(quotient)
except Exception as e:
print 'Something exceptional occurred!'
print e
Now we catch the exception, the signal that something exceptional happened. We put the signal in the variable e and we print it. Now your program will result in
Something exceptional occurred!
integer division or modulo by zero
When the ZeroDivisionError exception occurred, it stopped the execution at that spot, and went straight to the exception handler. We can also manually raise exceptions if we want to.
try:
print 'This you will see'
raise Exception('i broke your code')
print 'This you will not'
except Exception as e:
print 'But this you will. And this is the exception that occurred:'
print e
The raise keyword manually sends an exception signal. There are different kinds of exceptions, like the ZeroDivisionError exception, the AssertionError exception, the NotImplementedError exception and tons more, but I leave those for further studies.
In your original code, there was nothing exceptional happening, so that's why you never saw an exception getting triggered. If you want to trigger an exception based on a condition (like g > h) you can use the assert keyword, which behaves a little like raise, but it only raises an exception when the condition is false. So if you write
try:
print 'Is all going well?'
assert 3 > 5
print 'Apparently so!'
except AssertionError as e:
print 'Nope, it does not!'
You will never see the "Apparently so!" message, since the assertion is false and it triggers an exception. Assertion are useful for making sure values make sense in your program and you want to abort the current operation if they don't.
(Note that I caught explicitly the AssertionError in my exception handling code. This will not catch other exceptions, only AssertionErrors. You'll get to this in no time if you continue reading about exceptions. Don't worry too much about them now.)
You're not actually ever raising an exception. To raise an exception, you need to use the raise keyword with an Exception class or instance of an Exception class. In this case, I would recommend a ValueError as you've gotten a bad value.
fileo = "C:/Users/bgbesase/Documents/Brent/ParsePractice/out.txt"
g = 4
h = 6
try:
if g > h:
raise ValueError('Hey')
except Exception as e:
f = open(fileo, 'w')
f.truncate()
f.write(str(e))
f.close()
print e