Skip to the next iteration if a warning is raised [duplicate] - python

This question already has answers here:
In Python, how does one catch warnings as if they were exceptions?
(8 answers)
Closed 7 days ago.
How can I skip the iteration if warning is raised
Suppose I have the code below
import warnings
# The function that might raise a warning
def my_func(x):
if x % 2 != 0:
warnings.warn("This is a warning")
return "Problem"
else:
return "No Problem"
for i in range(10):
try:
# code that may raise a warning
k = my_func(i)
except Warning:
# skip to the next iteration if a warning is raised
continue
# rest of the code
print(i, " : ",k) # Only print this if warning was not raised in try:except
I would expect this to print only even numbers as my_funct(i) will raise a warning for odd numbers
update:
my_func(i) was used just for illustration purposes, the actual problem I want to use might not have an obvious returned value that raises a warning.

Warnings don't throw an exception by default.
You can specify warnings to throw an exception.
Just run this right after the import
warnings.simplefilter("error")
Or, you can just check the result of the function. Check if the result was "Problem" or "No Problem".
for i in range(10):
k = my_func(i)
if k == "Problem":
continue
# rest of the code
print(i, " : ",k)

Instead of using warn function throw a warning object that except will detect.
CODE:
import warnings
# The function that might raise a warning
def my_func(x):
if x % 2 != 0:
raise Warning('This is a warming')
else:
return "No Problem"
for i in range(10):
try:
# code that may raise a warning
k = my_func(i)
except Warning:
continue
print(i, " : ",k)
OUTPUT:
0 : No Problem
2 : No Problem
4 : No Problem
6 : No Problem
8 : No Problem

Related

Why is a StopIteration exception raised by a generator not caught by try/except block?

I have the following code:
def collatz_gen(n):
if (n == 0):
raise StopIteration("Cannot compute a Collatz chain starting at 0.")
yield n
while True:
if (n%2 == 0):
n = n//2
yield n
else:
if n==1:
raise StopIteration("Cannot generate past the first incident of 1 in the Collatz chain.")
n = (3 * n + 1)
yield n
def collatz_len(n):
collatz = collatz_gen(n)
count = 0
while True:
try:
x = next(collatz)
count += 1
except StopIteration:
return count
The problem is that catching the StopIteration does not work: the collatz_len method fails with a RunTimeError despite the try/except StopIteration block.
I know how to fix this: as per this answer, changing the StopIteration exceptions to ValueError allows the code to complete as expected.
The documentation has this to say:
If a generator code directly or indirectly raises StopIteration, it is
converted into a RuntimeError (retaining the StopIteration as the new
exception’s cause).
I guess I'm trying to understand why this decision was taken: is it not natural to catch a StopIteration exception when your generator runs out of values? What's the upside of forcing it to be converted to the more general RunTimeError?

What is the proper way to write this exception handling?

I only want my list to have one element in it. There should be one exception raised if the list is empty and a different exception raised if the list has more than one element.
The following code accomplishes the task, but I don't think it's written as well as it should by any standards out there. Additionally, if the condition is met that the list is greater than one, I want it to print the python error "index out of range" as it does in the other condition. How can I improve upon this?
x = []
try:
if len(x) > 1:
raise Exception
else:
testVar = x[0]
except IndexError as e:
print(e)
print("list does not have any elements.")
except Exception as e:
print(e)
print("There are too many elements in the list.")
Here is a better way to write that.
def func(x):
if not x:
print("list does not have any elements.")
return None
if len(x) > 1:
print("There are too many elements in the list.")
return None
return x[0]
Note that if we omit the first three lines, then Python will automatically raise an IndexError when you refer to x[0].

Runtime vs Syntax vs Logic Errors for Python

I'm trying to identify a few errors in this code below and write which kind of error it is and replace it with the correct code. I've found the three but I have a question on differentiating whether one is a runtime or a logic error.
def mirror(word): # 1
result == '' # 2
ord_a = ord('a') # 3
ord_z = ord('z') # 4
for c in word[:-1]: # 5
value = ord('c') - ord_a # 6
new_value = ord_z - value # 7
result += chr(new_value) # 8
return result # 9
I've successfully identified 4 lines (line 2, line 5, line 6, line 9) and made adjustments (testing various inputs work in the new function) here:
def mirror(word): # 1
result = '' # 2 ##### runtime error* or logic?
ord_a = ord('a') # 3
ord_z = ord('z') # 4
for c in word[::-1]: # 5 ##### logic error (supposed to reverse slicing)
value = ord(c) - ord_a # 6 ##### logic error (ord(c) not ord('c'))
new_value = ord_z - value # 7
result += chr(new_value) # 8
return result # 9 ###### syntax error (wrong indent)
My question is would line 2 count as a runtime error or a logic error, given that in the erroneous code it was comparing equality "==" rather than referencing an assignment with "=" .
Cheers
The errors can be best delineated as follows:
A syntax error is something caught by the compiler/interpreter and it's incorrect use of the language itself. For example, for:, which is invalid Python.
A runtime error is a problem that cannot be detected before the code runs but causes an issue that is caught during the program run. An example would be x = open("nosuchfile.txt") because the file is checked for existence only at runtime.
A logic error is something that isn't caught, either at compile or runtime but which causes an issue. An example would be working out the sum of all numbers from one to n inclusive with the_sum = sum([x for x in range(n)] - that wouldn't include the n in the sum.
If you actually call the function with something like:
print("running")
mirror("hello")
you will see there are no syntax errors because it successfully starts running.
Using the definitions above:
result == '' is a runtime error, it detects that you are trying to compare the uninitialised result with something (a result = 7 before that makes the error go away).
Everything else is a logic error since it neither prevents compilation nor stops it running because of an unrecoverable fault.

Python Catching Exception But Printing Them

I have built a max heap and trying to extract max as long as there are elements. If there isn't I'm returning an IndexError. This the code I'm trying to execute:
while True:
try:
print hp.extract_max()
except:
break
and in the extract_max() method:
def extract_max(self):
if self.size == 0:
return IndexError
item = self.items[0]
self.items[0] = self.items[self.size - 1]
self.heapify_down()
del self.items[len(self.items) - 1]
return item
However, the code is not breaking upon encountering an IndexError, rather printing it too. The while loop is not breaking.
<type 'exceptions.IndexError'>
<type 'exceptions.IndexError'>
....
it keeps printing the exception, without breaking the loop.
What's the problem?
As the other answer stated, you should raise the exception instead of return so:
if self.size == 0:
raise IndexError
I just want to add that you are catching all type of exceptions with except, you might want to change it to catch IndexError only to avoid catching other exceptions (ex: KeyboardInterrupt) as the following:
while True:
try:
print hp.extract_max()
except IndexError:
break
You should be raising an exception, not returning it. Do raise IndexError.

Using a boolean in returned tuple for "if" statement?

Current situation:
def isTooLarge(intValue):
if intValue > 100: print "too large"; return True
return False
if isTooLarge(101): break
Now I like to make the function more "library-friendly" by returning the errormessagetext instead of printing it:
def isTooLarge(intValue):
if intValue > 100: return True, "too large"
return False
bln,str = isTooLarge(101)
if bln: specialprint(str); break
Any idea how I can evaluate it as an one-liner again? (something like "if ,str isTooLarge(101): specialprint(str); break" or what is the Python way here?
No problem to put the errormessage into a global variable like "lasterrormessage" and keep the rest as is.
You can be much more "library friendly" by using errors like they are meant for, as errors:
def CheckNotTooLarge(intValue):
if intValue > 100:
raise ValueError("too large") #or AssertionError
return #or maybe do something else?
then a user could use the error message completely separately using try: except:
try:
CheckNotTooLarge(101)
except ValueError:
traceback.print_exc() #print error message
#handle too large
else:
#handle not too large
I can see how this would quickly get annoying if you just want to check without handling errors so I'd recommend having two functions, one that just returns a boolean, no extra work and another that raises/returns the error text:
def isTooLarge(intValue):
return intValue<=100 #now this is a one liner!
def checkIsTooLarge(intValue):
"uses isTooLarge to return an error text if the number is too large"
if isTooLarge(intValue):
return "too large" #or raise ...
else:
return False
def isTooLarge(intValue):
return "too large" if intValue > 100 else False
x = isTooLarge(101); x and print(x)
However. Please don't do this. Exceptions exist for a reason. Putting things in one line simply for the sake of it makes your code hard to read.

Categories

Resources