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)
If I put a try: except block on this if statement, will the return 0 condition be reported as an exception?
(The if statements below are inside a method)
if x:
do something
elif y:
do something
else:
print("Please use valid condition")
return 0
In the case I am looping into a list, where for value msg_list = 0 it will execute action(0), usr). This action can fail for a determined user, I should choose aother user if it happens, perform all the actions related to the user
How can I do to repeat action[0] if it fails?
for msg in range(len(msg_list)):
# in this case msg = 0
usr = select_random_user()
multiple_actions_for(usr) # This are lots of code lines I don't want to repeat!!
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
go_back_to(msg =0 instead of looping into msg=1) # this is what I want to do
How can I do to get that? Repeat the loop for msg = i instead of passing to msg = i + 1?
Put your code into the endless while-loop with exiting from it if try was successful:
for msg in range(len(msg_list)):
while True:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
except Exception as e:
continue
else:
break
It really depends. Is it okay to go back to the beginning of the loop? If so, you can call "continue", which stops the current iteration, and restarts the loop. Otherwise, I don't think there's something similar to a goto in Python, no. It's a very structured language.
Try using while loop instead of for loop. The idea is as shown bellow:
bool still_looping = True
msg = 0
while still_looping:
usr = select_random_user()
multiple_actions_for(usr)
try:
action(msg, usr)
more_actions(usr.related_stuff)
if (msg < len (msg_list)):
msg += 1
except Exception as e:
# Do whatever you want here. msg was not incremented
if (msg == len(msg_list))
still_looping = False #verify if this was the last execution
I'm trying to rerun a try-except loop each time there is an error and only break when there is no error.
loop = True;
while loop == True:
try:
for i in data_names:
#do something
except Exception, e:
e = str(e)[0:100];
parse_error_list.append(str(e)[str(e).rindex(':')+2:str(e).rindex(':')+4]);
if len(e) == 0:
loop = False;
As a sanity check, will the following allow me to exit the loop if and only if there is no error?
EDIT: Is the answer? If so, is this the most efficient implementation? ...
loop = True;
while loop:
try:
for i in data_names:
#do something
except Exception, e:
e = str(e)[0:100];
parse_error_list.append(str(e)[str(e).rindex(':')+2:str(e).rindex(':')+4]);
if e:
loop = False;
The neatest solution would probably resemble:
while True:
try:
for i in data_names:
#do something
except Exception, e:
#log or otherwise handle exception
else:
break
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.