How to catch exceptions elegantly in this situation?

S

Saqib Ali

Check out the following code fragment

Line 1: myDict = {}
Line 2: a = 5
Line 3: b = 2
Line 4: c = 0
Line 5: myDict["A"] = a + b + c
Line 6: myDict["B"] = a - b - c
Line 7: myDict["C"] = a * b * c
Line 8: myDict["D"] = a / b / c
Line 9: myDict["E"] = a ** b ** c
Line 10: ...<etc>...
Line 11: ...<etc>...
Line 12: ...<etc>...

An exception will be raised at line #7 because of division by zero.
I want the exception to be caught, printed, but then I want the flow
to continue to line #8 and onwards. I want this behaviour on EACH
assignment line. (Line 5 onwards). IE: Do the assignment. If an
exception is raised, print the exception and continue to the next
assignment.

I can't think of an elegant way to handle this. Can someone help?

- I COULD surround each assignment line with a try/except block. But
that seems very tedious, cumbersome and unwieldy.

- Alternatively I tought of writing a function 'myFunc' and passing in
the args as follows: (dict=myDict, key="D", expression="a / b / c"). I
figured within 'myFunc' I would do: myDict[key] = eval(expression)
........... However that wouldn't work either because the eval would
fail since the variables will be out of context.

Any Suggestions??

-Saqib
 
B

Brian van den Broek

Saqib Ali said unto the world upon 2004-10-07 23:13:
Check out the following code fragment

Line 1: myDict = {}
Line 2: a = 5
Line 3: b = 2
Line 4: c = 0
Line 5: myDict["A"] = a + b + c
Line 6: myDict["B"] = a - b - c
Line 7: myDict["C"] = a * b * c
Line 8: myDict["D"] = a / b / c
Line 9: myDict["E"] = a ** b ** c
Line 10: ...<etc>...
Line 11: ...<etc>...
Line 12: ...<etc>...

An exception will be raised at line #7 because of division by zero.
I want the exception to be caught, printed, but then I want the flow
to continue to line #8 and onwards. I want this behaviour on EACH
assignment line. (Line 5 onwards). IE: Do the assignment. If an
exception is raised, print the exception and continue to the next
assignment.

I can't think of an elegant way to handle this. Can someone help?

- I COULD surround each assignment line with a try/except block. But
that seems very tedious, cumbersome and unwieldy.

- Alternatively I tought of writing a function 'myFunc' and passing in
the args as follows: (dict=myDict, key="D", expression="a / b / c"). I
figured within 'myFunc' I would do: myDict[key] = eval(expression)
.......... However that wouldn't work either because the eval would
fail since the variables will be out of context.

Any Suggestions??

-Saqib

Hi Saqib,

I'm still learning and my skills are modest, so I'm posting this as much
to learn what is wrong with it as to offer help to you. But what about:
>>> a = 1
>>> a = 5
>>> b = 2
>>> c = 0
>>> my_dict = {}
>>> key_list = ['A', 'B', 'C']
>>> value_list = ['a + b +c', 'a / b / c', 'a - b - c']
>>> dict_ingredients = zip(key_list, value_list)
>>> for (k, v) in dict_ingredients:
.... try:
.... my_dict[k] = eval(v)
.... except ZeroDivisionError:
.... pass
....
 
P

Paul Rubin

- Alternatively I tought of writing a function 'myFunc' and passing in
the args as follows: (dict=myDict, key="D", expression="a / b / c"). I
figured within 'myFunc' I would do: myDict[key] = eval(expression)
.......... However that wouldn't work either because the eval would
fail since the variables will be out of context.

Any Suggestions??

exprs = [("A", "a+b+c"), ("B", "a-b-c"), ("C", "a/b/c"), etc.]
for a,e in expr:
try:
myDict[a] = eval(e)
except ArithmeticError:
# whatever
 
J

Jeremy Bowers

Check out the following code fragment

Line 1: myDict = {}
Line 2: a = 5
Line 3: b = 2
Line 4: c = 0
Line 5: myDict["A"] = a + b + c
Line 6: myDict["B"] = a - b - c
Line 7: myDict["C"] = a * b * c
Line 8: myDict["D"] = a / b / c
Line 9: myDict["E"] = a ** b ** c
Line 10: ...<etc>...
Line 11: ...<etc>...
Line 12: ...<etc>...

Can you give me more detail? What is the real problem?

For example, for the code you give above, I think I would do:

import operator
myDict = {}
a = 5
b = 2
c = 0

def doOp(key, op):
try:
tmp = op(a, b)
myDict[key] = op(tmp, c)
except: # probably ought to narrow this down
pass

for key, op in (("A", operator.add), ("B", operator.sub),
("C", operator.mul), ("D", operator.div),
("E", operator.pow)):
doOp(key, op)


but with a better idea of the problem domain I may be able to be more
helpful.

Of course, this may start you on the path to a better idea.

Another, more generic possibility is to wrap your operations in a
function, or a lambda, and pass them in to some object to be evaluated in
a safe context. Depending on the domain, you may find a clever way to
collapse the problem so it isn't so cumbersome. For my solution, I'm
expecting that "...<etc>..." represents many more lines.

Oh, and unofficially, I recommend either "import operator as op" or "from
operator import *". But you didn't hear that from me. (I find I'm slightly
less "import *" phobic than many around here, if the module is a vital
part of the flow of the code and net-net, the repeated invocation of the
module name impedes reading the code. In the above fragment, I think
"operator." meets that standard. If this were a small part of a large
module, I wouldn't do it.)
 
S

Saqib Ali

Jeremy Bowers said:
On Thu, 07 Oct 2004 20:13:06 -0700, Saqib Ali wrote:


Can you give me more detail? What is the real problem?


Sure.
The real issue is that I am doing some screen-scraping from on-line
white pages (residential telephone directory).

I have defined a bunch of regular expressions and myFunc() populates a
dictionary corresponding to each result from the white pages.

So essentially myDict corresponds to a single record found. See below

myDict["fullName"] = fullNameRegExp.match(htmlText)[0]
myDict["telNum"] = telNumRegExp.match(htmlText)[0]
myDict["streetAddr"] = streetAddrRegExp.match(htmlText)[0]
myDict["city"] = cityRegExp.match(htmlText)[0]
myDict["state"] = stateRegExp.match(htmlText)[0]
myDict["zip"] = zipRegExp.match(htmlText)[0]


Sometimes one or more of these regexps fails to match. In which Case
an exception will be raised. I want to catch the exception, print out
a message..... but then keep on going to the next assignment
statement.


How can I do that without wrapping each assignment in its own
try/except block??







Jeremy Bowers said:
Check out the following code fragment

Line 1: myDict = {}
Line 2: a = 5
Line 3: b = 2
Line 4: c = 0
Line 5: myDict["A"] = a + b + c
Line 6: myDict["B"] = a - b - c
Line 7: myDict["C"] = a * b * c
Line 8: myDict["D"] = a / b / c
Line 9: myDict["E"] = a ** b ** c
Line 10: ...<etc>...
Line 11: ...<etc>...
Line 12: ...<etc>...

Can you give me more detail? What is the real problem?

For example, for the code you give above, I think I would do:

import operator
myDict = {}
a = 5
b = 2
c = 0

def doOp(key, op):
try:
tmp = op(a, b)
myDict[key] = op(tmp, c)
except: # probably ought to narrow this down
pass

for key, op in (("A", operator.add), ("B", operator.sub),
("C", operator.mul), ("D", operator.div),
("E", operator.pow)):
doOp(key, op)


but with a better idea of the problem domain I may be able to be more
helpful.

Of course, this may start you on the path to a better idea.

Another, more generic possibility is to wrap your operations in a
function, or a lambda, and pass them in to some object to be evaluated in
a safe context. Depending on the domain, you may find a clever way to
collapse the problem so it isn't so cumbersome. For my solution, I'm
expecting that "...<etc>..." represents many more lines.

Oh, and unofficially, I recommend either "import operator as op" or "from
operator import *". But you didn't hear that from me. (I find I'm slightly
less "import *" phobic than many around here, if the module is a vital
part of the flow of the code and net-net, the repeated invocation of the
module name impedes reading the code. In the above fragment, I think
"operator." meets that standard. If this were a small part of a large
module, I wouldn't do it.)
 
B

Bengt Richter

Jeremy Bowers said:
On Thu, 07 Oct 2004 20:13:06 -0700, Saqib Ali wrote:


Can you give me more detail? What is the real problem?


Sure.
The real issue is that I am doing some screen-scraping from on-line
white pages (residential telephone directory).

I have defined a bunch of regular expressions and myFunc() populates a
dictionary corresponding to each result from the white pages.

So essentially myDict corresponds to a single record found. See below

myDict["fullName"] = fullNameRegExp.match(htmlText)[0]
myDict["telNum"] = telNumRegExp.match(htmlText)[0]
myDict["streetAddr"] = streetAddrRegExp.match(htmlText)[0]
myDict["city"] = cityRegExp.match(htmlText)[0]
myDict["state"] = stateRegExp.match(htmlText)[0]
myDict["zip"] = zipRegExp.match(htmlText)[0]


Sometimes one or more of these regexps fails to match. In which Case
an exception will be raised. I want to catch the exception, print out
a message..... but then keep on going to the next assignment
statement.


How can I do that without wrapping each assignment in its own
try/except block??
What exception are you getting? TypeError on unsubscriptable object?

How about (untested) something like:

for key in 'fullName telNum streetAddr city state zip'.split():
m = getattr(locals()[key+'RegExp'], 'match')(htmlText)
if m is None: print 'Error: % not found' % key
else: myDict[key] = m.group()

Obviously you could do something cleaner than silly locals() and getattr stuff by using a
prepared dict, e.g. rxDict == {fullName:fullnameRegExp.match, ...}, something like (untested)

for key, matcher in rxDict.items():
m = matcher(htmlText)
if m is None: print 'Error: % not found' % key
else: myDict[key] = m.group()

Or, if you just put '?' as value where nothing is found, you can get the dict in one line (untested ;-):

myDict = dict([(k,m is None and '?' or m.group()) for k,m in [(k2,mat(htmlText) for k2,mat in rxDict.items()]])

Regards,
Bengt Richter
 
M

Mel Wilson

Jeremy Bowers said:
On Thu, 07 Oct 2004 20:13:06 -0700, Saqib Ali wrote:


Can you give me more detail? What is the real problem?


Sure.
The real issue is that I am doing some screen-scraping from on-line
white pages (residential telephone directory).

I have defined a bunch of regular expressions and myFunc() populates a
dictionary corresponding to each result from the white pages.

So essentially myDict corresponds to a single record found. See below

myDict["fullName"] = fullNameRegExp.match(htmlText)[0]
myDict["telNum"] = telNumRegExp.match(htmlText)[0]
myDict["streetAddr"] = streetAddrRegExp.match(htmlText)[0]
myDict["city"] = cityRegExp.match(htmlText)[0]
myDict["state"] = stateRegExp.match(htmlText)[0]
myDict["zip"] = zipRegExp.match(htmlText)[0]


Sometimes one or more of these regexps fails to match. In which Case
an exception will be raised. I want to catch the exception, print out
a message..... but then keep on going to the next assignment
statement.

I'd be tempted to try

redict = {"fullname": fullNameRegExp,
"telNum": telNumRegExp,
"streetAddr": streetAddrRegExp,
"city": cityRegExp,
"state": stateRegExp,
"zip": zipRegExp,
}

for x in redict:
try:
myDict[x] = redict[x].match (htmlText)[0]
except whichever_error:
pass



Regards. Mel.
 
S

Steve Holden

Saqib said:
Check out the following code fragment

Line 1: myDict = {}
Line 2: a = 5
Line 3: b = 2
Line 4: c = 0
Line 5: myDict["A"] = a + b + c
Line 6: myDict["B"] = a - b - c
Line 7: myDict["C"] = a * b * c
Line 8: myDict["D"] = a / b / c
Line 9: myDict["E"] = a ** b ** c
Line 10: ...<etc>...
Line 11: ...<etc>...
Line 12: ...<etc>...

An exception will be raised at line #7 because of division by zero.
I want the exception to be caught, printed, but then I want the flow
to continue to line #8 and onwards. I want this behaviour on EACH
assignment line. (Line 5 onwards). IE: Do the assignment. If an
exception is raised, print the exception and continue to the next
assignment.

I can't think of an elegant way to handle this. Can someone help?

- I COULD surround each assignment line with a try/except block. But
that seems very tedious, cumbersome and unwieldy.

- Alternatively I tought of writing a function 'myFunc' and passing in
the args as follows: (dict=myDict, key="D", expression="a / b / c"). I
figured within 'myFunc' I would do: myDict[key] = eval(expression)
........... However that wouldn't work either because the eval would
fail since the variables will be out of context.

Any Suggestions??
Read the recent thread on resumab le exceptions: it isn't available
right now, and it doesn;t seem likely to be.

regards
Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top