How to check for several exceptions within one exception block? - python

I want to catch several exceptions on the same line, but have different outcome depending on which exception is triggered. I'm trying to summarize a set of numbers in a text file and want to check on value and io errors.
try:
filex = open('test.txt', 'r')
number = filex.readline().rstrip('\n')
added = 0
while number != '':
added += int(number)
number = filex.readline().rstrip('\n')
print(added)
filex.close()
except (IOError,ValueError):
if IOError:
print('IOError')
else:
print('ValueError')
The issue I'm having is that it will always trigger on the first condition of the IF test.

can use two except for this condition like this
try
.......
except IOError:
print('IOError')
except ValueError:
print('ValueError')

I recommend using one clause per exception. Here is the "I'm stubborn" version:
try:
filex = open('test.txt', 'r')
number = filex.readline().rstrip('\n')
added = 0
while number != '':
added += int(number)
number = filex.readline().rstrip('\n')
print(added)
filex.close()
except (IOError,ValueError) as e:
if isinstance(e, IOError):
print('IOError')
else:
print('ValueError')
Here's the clause-per-exception version:
try:
filex = open('test.txt', 'r')
number = filex.readline().rstrip('\n')
added = 0
while number != '':
added += int(number)
number = filex.readline().rstrip('\n')
print(added)
filex.close()
except IOError:
print('IOError')
except ValueError:
print('ValueError')
You can see that in the first version, you have to implement type checking, which Python's exception handling would otherwise give you for free. And the second version is slightly shorter, too.

if IOError:
I think this line checks the trueness of the class IOError. It ignores the type of error that was raised.
You could maybe do something like :
except (IOError, ValueError) as e:
if instanceof(e, IOError):
#...

Related

Python exception: execute code if a specific exception is raised or else

Let's say I have the following code, that assign 1 and print it in case the value is None or not negative.
value = None
class NegativeNumber(Exception):
pass
class NotFound(Exception):
pass
try:
if value is None:
raise NotFound
elif value < 0:
raise NegativeNumber
except NegativeNumber:
print("Error: negative number")
except NotFound:
value = 1
print(value)
else:
value = 1
print(value)
Is there a way to avoid repeat twice to assign value=1 and print it?
It would be ideal something like except NotFound or else, but I have not found anything similar in python.
There is no except ... or else: construct. Suppress the exception inside the try block to trigger the else block for the exception as well:
try:
try:
if value is None:
raise NotFound
elif value < 0:
raise NegativeNumber
except NotFound:
pass # suppress exception
except NegativeNumber:
print("Error: negative number")
else:
value = 1
print(value)
Instead of using try/except to suppress the exception, contextlib.suppress can be used instead. This can make the intention clearer, as it explicitly names how the exception is handled.
try:
with suppress(NotFound):
if value is None:
raise NotFound
elif value < 0:
raise NegativeNumber
except NegativeNumber:
print("Error: negative number")
else:
value = 1
print(value)

Unable to get the type of data user inputs

I am trying to get the type of data user inputs, but I am getting some issues with code. I tried with the below code:
def user_input_type():
try:
user_input = int(raw_input("Enter set of characters or digit"))
except:
try:
user_input = str(user_input)
except Exception as e:
print e
return type(user_input)
return type(user_input)
print user_input_type()
but it gives me 2 warnings before running the code.
Local variable user_input might be referenced before assignment.
Too broad exception clause such as no exception class specified, or specified as Exception.
After running the code when I enter digits it gives me proper value but when I enter character it gives me an error:
UnboundLocalError: local variable 'user_input' referenced before assignment
Please help.
You need to set the 'user_input' outside of the try-catch.
Ex:
def user_input_type():
user_input = raw_input("Enter set of characters or digit") #---->Outside try-except
try:
user_input = int(user_input)
except:
try:
user_input = str(user_input)
except Exception as e:
print e
return type(user_input)
print user_input_type()

Try/Except if function is false

I have a function which works out whether or not the file is in a n x n square matrix i.e. 3x3 or 4x4. Now if I call the function it works fine; it says whether or not it is a nxn square.
My problem is I want to use an exception, if the function returns a False value, then it wont load the text file but give a error saying to ensure the file has a nxn grid.
So for example if I have the grid stored in a text file and I try to load it with python code; the program should keep looping until the file is in the correct format. I wasn't sure if there was an exception for a function boolean
ABC
DEF
GHI
J
Currently I have
def grid(n):
rows = len(n)
for row in n:
if len(row) != rows:
return False
Similar to how the file open works; if it doesn't exist (FileNotFoundError) then it'll keep looping until it finds the input file name
Here's one way to do it. Simply raise an appropriate exception if square(d) returns False.
#Return True if sq is square, False otherwise
def square(sq):
rows = len(sq)
return all(len(row) == rows for row in sq)
def loaddata():
while True:
try:
filename = input("Enter the name of the file to open: ") + ".txt"
with open(filename, "r") as f:
d = []
for line in f:
splitLine = line.split()
d.append(splitLine)
if not square(d):
raise ValueError
break
except FileNotFoundError:
print("File name does not exist; please try again")
except ValueError:
print("The format is incorrect")
for line in d:
print("".join(line))
We reset d to [] each time through the loop in case we need to get rid of the contents of a previous file that isn't square.
You're confusing handing the exception (the "except" statement) with raising one. What you should do in square is raise an exception instead of returning false and then handle it in your main program:
def square(sq):
rows = len(sq)
for row in sq:
if len(row) != rows:
raise ValueError("the format is incorrect")
def loaddata():
while True:
try:
filename=input("Enter the name of the file to open: ") + ".txt"
with open(filename,"r") as f:
for line in f:
splitLine=line.split()
d.append(splitLine)
break
square(d)
except FileNotFoundError:
print("File name does not exist; please try again")
except ValueError:
print("The format is incorrect")
for line in d:
print("".join(line))
return

Why this is unexpected indentation in Python?

#!/usr/bin/python
try:
f = open("/home/masi/r.raw", "r+")
aBuf = f.seek(4)
except:
print "Error at position : ", position
events = []
for i in range(100):
aBuf = f.seek(4);
try:
if aBuf[:4] == b'\xFA\xFA\xFA\xFA':
print("E")
except:
# print "\0"
f.close()
when I commented out the print of except, I get the error
f.close()
^
IndentationError: expected an indented block
I think I need to have try-except because the if-clause is false often.
Why do I get this unexpected indendation?
except is expecting one or more statements.
You could write:
try:
if aBuf[:4] == b'\xFA\xFA\xFA\xFA':
print("E")
except:
pass
Warning
As stated in the comments, it is not a good practice to use except: pass.
See Why is “except: pass” a bad programming practice?.
Your code from events = [] and down needs to be inside of the first try..except block. The f.close() is out of scope.

Python: Is it possible to have multiple exceptions statments for a try block?

try:
case_no = re.search("Case Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
except:
try:
try:
case_no = re.search("Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
except:
case_no = re.search("Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
except:
case_no = "N/A"
As you can see the above code is quite clumsy. I want to know if there is any way I can do like this.
try:
XYZ
except:
DOXYZ
except:
DOXYZ
Basically I want to be able to use - "try X if exception then try Y if exception then try Z" without nesting too much statemtns.
Probably you shouldn't be checking exception at all?
patterns = [
"Case Number:</span></td><td><span class=\"Value\">([^<]*?)<",
"Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<",
"Citation Number:</span></td><td><span class=\"Value\">([^<]*?)<" # same as #2?
]
text = br.response().read()
case_no = "N/A"
for pattern in patterns:
res = re.search(pattern, text)
if res:
case_no = res.group(1)
break
Yes, it is posible, as long as you define exception condition...
Like:
try:
f = open('myfile.txt')
s = f.readline()
i = int(s.strip())
except IOError as (errno, strerror):
print "I/O error({0}): {1}".format(errno, strerror)
except ValueError:
print "Could not convert data to an integer."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
But, you must define the exception type.
A common idiom for the behavior you're looking for is something like:
try: foo()
except: pass
try: bar()
except: pass
But you should always catch a specific exception and make sure it makes sense. In your case it simply doesn't make sense - to see if the regular expression matched, test the result for None:
r = br.response().read()
PATTERN1="..."
PATTERN2="..."
PATTERN3="..."
mo = re.search(PATTERN1, r) or re.search(PATTERN2, r) or re.search(PATTERN3, r)
case_no = mo.group(1) if mo else "N/A"
For performance reasons you can precompile your regexes:
RE1 = re.compile("...")
RE2 = re.compile("...")
RE3 = re.compile("...")
mo = RE1.search(r) or RE2.search(r) or RE3.search(r)
Also, for your specific regex patterns you can easily combine them into one, and using a named group can help readability:
pat = r"""(Case|Citation) Number:</span></td><td><span class="Value">(?P<case_no>[^<]*?)<"""
mo = re.search(pat, r)
case_no = mo.group("case_no") if mo else "N/A"
And finally, using regular expressions to parse HTML is the road to disaster, consider using HTMLParser from the standard lib or Beautiful Soup.
No, it is not possible to do what you want. the semantics of multiple except clauses covers catching different types of exceptions that may be thrown from the same block of code. You must nest the statements or rethink your code to get the desired results.
This might be a case where it would be better to test for the preconditions that you expect to cause an exception.
if test1():
#dox
elif test2():
#doy
elif test3():
#doz
etc.
I would also recommend against using catchall except: phrases except in very specialized circumstances where you know you need them.
I'd avoid the exceptions if I were doing this:
count = 3
caseRe = re.compile("Case Number:</span></td><td><span class=\"Value\">([^<]*?)<")
while count > 0:
text = br.response().read()
mo = caseRe.search(text)
if mo is None:
count -= 1
continue
case_no = mo.group(1)
break
if count == 0:
case_no = "N/A"
You'd be better off restructuring your code:
success = False
for _ in xrange(MAX_ATTEMPTS):
try:
XYZ
success = True
break
except:
pass
if not success:
DOXYZ
It's better to explicitly specify the exception, though. Do you really want to catch KeyboardInterrupts?
If you're doing the same or a similar thing in every try/except block, you might use a loop
case_no = "N/A"
for _ in range(3):
try:
case_no = re.search("Case Number:</span></td><td><span class=\"Value\">([^<]*?)<",br.response().read()).group(1)
break
except SomeExplicitlyCaughtExceptions:
pass
Of course it makes no sense in this form, because trying the same thing three times will yield the same result.

Categories

Resources