tags:

views:

114

answers:

7
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.

+1  A: 

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.

FallenAngel
This isn't really what the OP's trying to do, though.
detly
Yes, but basically, you can not execute try catch blocks as you execute switch or if blocks.Using if or switch is better that try-except. Because purpose of using try-catch is not suitable for a such condition...
FallenAngel
A: 

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.

jellybean
I imagine `br.response().read()` will be different each time.
Douglas Leeder
That's not true.If we're talking about a web service or a OS service you might want to perform the operation again in case it might be online and only log that the request timedout last time.
the_drow
`case_no = "N/A"` should probably be indented?
Douglas Leeder
Oh, there's a `read` in there ... I just copied the recurring line into my code and missed that. :) Edited to assign the default value at the beginning.
jellybean
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?

detly
You probably want to break out of the `for` on success.
Douglas Leeder
and after you `break` on success, you can use an `else` clause on the `for` to process the ` not success` case and drop that flag all together.
aaronasterling
Oops, fixed now.
detly
@aaronasterling - yeah, but almost no-one knows what an else clause on a loop in Python is for.
detly
@detly thats because almost nobody uses them
aaronasterling
+2  A: 

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.

aaronasterling
+5  A: 

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
KennyTM
+3  A: 

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.

orip
A: 

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"
Douglas Leeder