[Tutor] Line in a file
alan.gauld@bt.com
alan.gauld@bt.com
Fri, 19 Jul 2002 17:37:59 +0100
> My first question about the above code, is why couldn't I put an
> exception handler in there with the finally? I thought that
> you could do this
Nope you have to nest them:
try:
try:
#do it here
except: # catch errors
finally: #tidy up
Which try goes inside is a fairly arbitrary choice, I prefer
the finally outside because it then comes finally in the code too...
> So then I tried it this way:
>
> >>> def printline(fh, num):
> ... c = 0
> ... try:
> ... for line in fh.xreadlines():
> ... c = c + 1
> ... if (c == num):
> ... return line
> ... raise IndexError
> ... except IndexError:
> ... print "The line you want was not found.\n"
The problem is you are raising and catching the exception,
you only want to raise it so that your user can catch it!
remove the try/except and keep the raise.
(sounds like a poker game!)
then wrap the call to your function in a try/except:
>>> def printline(fh, num):
... c = 0
... for line in fh.xreadlines():
... c = c + 1
... if (c == num):
... return line
... raise IndexError
...
>>> try: printline(f,27)
... except IndexError: print "Couldn't access line 27"
...
Of course you also should define the IndexError
exception class too:
class IndexError(Exception): pass
> it seems like I'm not using proper style.
You are trying to handle your own exception rather
than raising it for your user to catch.
> Anyways, with this version, there's no "finally", so I can't
> reset the file pointer with fh.seek(0).
But you can now we;'ve removed the try/catch
>>> class IndexError(Exception): pass
>>> def printline(fh, num):
... c = 0
... try:
... for line in fh.xreadlines():
... c = c + 1
... if (c == num):
... return line
... finally: fh.seek(0)
... raise IndexError()
> I liked it better the first time.
Is that any better?
> By doing it this way,
Exactly right. I should have read further before
'explaining'!
> It seems like I should be able to just have the
> exception handler defined within the function definition
No, you want a way to signal to the function user that
an error occured, that's exactly what raise is for. It
only makes sense for you to handle the exception if you
know how to recover from it. Given that you don't know
how the client wants to deal with a non existent line
you have to pass responsibility back to them!
> want to use "finally" to reset my file pointer. Is this
> really the way it's supposed to work?
Absolutely. The finally is something that you as function
writer want to guaranrtee about the function - namely that
it returns the line requested and leaves the file pointer
at 0.
> Extra credit: can someone give me a clue as to how to make my
> "printline()" function a method of a file pointer, so
> that instead of
You'd need to create your own file subclass:
class RandomFile:
def __init__(fn,md='r'):
self.fp = open(fn,md)
def printLine(num): # code here
# and other file methods
Now you can open your class:
try:
fp = RandomFile('foo.txt','r')
fp.printline(27)
except: print 'oops!'
> That seems like the way it should be done. I seems like I'll have to
> extend the file pointer class. But not sure...
Yes, if thats an extensible class, or there might be a
UserFile or somesuch. But thats what you'll need to do.
Alan G.