简体   繁体   中英

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.

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.

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 KeyboardInterrupt s?

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"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM