On Aug 27, 5:35 pm, [EMAIL PROTECTED] wrote: > I have: > > try: > for line in open(myFileName): > count += 1 > except IOError: > print "Can't open myfile" > > (I know, this is bad, I never close the file, but its just for > illustration). But then I change it to: > > try: > for line in open(myFileName): > count += openAndProcessSubfile(line) > except IOError: > print "Can't open myfile" > > ... now the 'except' incorrectly catches errors from > openAndProcessSubfile. > Of course, I can always do: > > try: > myFile = open(myFileName) > except IOError: > print "Can't open myfile" > for line in myFile: > count += openAndProcessSubfile(line) > > ...But if my compound statement is "with" instead of "for" that seems > to defeat the purpose: > > try: > myFile = open(myFileName) > except IOError: > print "Can't open myfile" > with myFile as anotherNameForMyFile: > ....
I suspect this isn't often complained about because this usage of try...except kind of misses the boat. The above treats the exception as nothing more than an error return code, but it's often not optimal to handle error so close to the call. The best reason to catch and handle an exception very close to the call is if you intend to recover from it right away. For example: try: f = open("fileA") except IOError: f = open("fileB") If you don't intend to recover right away, it's usually better to let the exception propogate until up the call chain until the point where you do want to recover. Consider this: is there any other code in your program that has to do something different based on whether you successfully opened this file or not? If so, how will you notify it whether the call has succeeded or not? Very often, the caller itself needs to know. You could, say, set a flag to indicate it's failed, but why do that when you could simply let the caller detect and handle the error itself? If you don't intend to recover at all, you should let it propogate up to the point where you will resume normal processing (for example: before the next input prompt), and handle it there. Especially if you're going to print an error message: printing an error message at the point the error occurs can severely limit code reusability. Enough rambling. Here's what I'd do in your situation: nothing. Don't handle the exception here at all. Let it raise IOError. My code would look like this: with open('myFile') as myFile: .... However, I would handle the exeption wherever I intended to take action based on success or failure. It looks like you are treating "file-not-found" as non-fatal, and other IOErrors as fatal? In that case, we would have to check the error code to distinguish, and reraise if not file not found. # this is the point where success or failure # determines what I do next, that's why I handle # the exception here. try: load_myFile() except IOError, e: if e.errno == 2: # file not found is usually errno 2 print "file not found" else: raise else: # load succeeded, do whatever. One other useful technique is recasting: catching an error close to the call, and raising a different error. Carl Banks -- http://mail.python.org/mailman/listinfo/python-list