#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    11
    Rep Power
    0

    File manipulation (try: except: finally:)


    Hi;

    Still trying to learn python. I'm playing around with files now. The books/tutorials that I've been reading suggest having a 'finally:' clause to the try/except to close the file. What I'm trying, though, doesn't seem clean to me:

    Code:
    #### imports:
    import sys
    
    file = '/etc/servces'
    try:
       fo = open(file)
    except:
       print 'no such file'
       sys.exit(1)
    finally:
       fo.close()
    
    print 'you made it this far!'
    The 'file' parameter is intentionally incorrect. At this particular juncture, I'd like to just print 'no such file' and exit. Yet, as the docs suggest, the finally: clause gets executed even with the sys.exit.

    Code:
    $ ./tn.py
    $ ./tn.py
    no such file
    Traceback (most recent call last):
      File "./tn.py", line 22, in <module>
        fo.close()
    NameError: name 'fo' is not defined
    Is there a right way to do this? Basically, I'm looking for something akin to the perl

    Code:
    finally:
       fo.close() if (defined(fo))  # to steal some code from perl
    I'd like to learn the right way to do this from the start instead of having to unlearn things later.. been down that road a wee bit too many times

    Thanks for any hints/tips/suggestion.

    // a few minutes later:

    Just read in the python cookbook that the open shouldn't be in the try statement.. so, the test of the open would be the attempt to read the file, then? Does that catch all errors (permission problems, file not there, etc?) The code in the cookbook says:

    Code:
    fo = open(file)
    try:
       for line in fo:  # chto-nibud' slyuchaets'ya zdes'
    finally:
       fo.close()
    // and yet a few minutes more:

    I found something that works; but it seems kind of kludgey ( I refer the reader to my earlier statement about learning the right way...)

    Code:
    #### imports:
    import sys
    
    file = '/etc/servces'
    try:
       fo = open(file)
    except IOError:
       print 'no such file'
       sys.exit(1)
       
    try:
       lines = fo.readlines()
    finally:
       fo.close()
    
    print 'you made it this far!'
    So, there're two try stanzas: one to check for errors on the file and the other to check on errors for reading the file. It seems like there should be a cleaner way of doing that.

    Once again, thanks for any hints/tips/suggestions.

    // and yet later still (last time, I promise)

    I think I came up with *a* right answer. Not sure if it's *the* right answer:

    Code:
    #### imports:
    import sys
    
    file = sys.argv[1]
    try:
       fo = open(file)
       try:
          lines = fo.readlines()
       except:
          print "Can't read file:", file
       finally:
          fo.close()
    except:
       print "Can't open file:", file
       sys.exit(1)
       
    print 'you made it this far!'
    execution:

    Code:
    $ ./tn.py /etc/services
    you made it this far!
    $ ./tn.py /etc/servces 
    Can't open file: /etc/servces
    That seems to satisfy the desire. Is that the accepted way to go about error checking file manipulation?

    Thanks again.

    Doug O'Leary
  2. #2
  3. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,612
    Rep Power
    4247
    Just do it something like this:
    Code:
    #!/usr/bin/python
    
    import sys
    
    file = '/etc/does_not_exist'
    
    fo = None
    try:
        fo = open(file)
    except:
        print('No such file')
        sys.exit(0)
    finally:
        if fo != None: fo.close()
    
    print('Made it this far')
    Note that I initialize fo (and set it to None) outside the try block so that it will be defined by the time it hits finally. Within the finally clause, I check to see if it is None or not and only close it if it is not None. This is similar to how the perl code does a:
    Code:
    close($fo) if defined($fo);
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jul 2007
    Location
    Joensuu, Finland
    Posts
    431
    Rep Power
    67
    Originally Posted by dkoleary
    The books/tutorials that I've been reading suggest having a 'finally:' clause to the try/except to close the file.
    I think that’s old information. The new correct way is to use “with”:

    Code:
    with open(file) as fo:
        # ...
    I would check the existence of the file beforehand with os.path.isfile() but I guess wrapping the above in a try...except block is OK too.
    My armada: openSUSE 13.1 (home desktop, home laptop), Crunchbang Linux 11 (mini laptop, work laptop), Android 4.2.1 (tablet)
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Feb 2013
    Posts
    11
    Rep Power
    0
    Hey;

    Thank you both! Very helpful. With some reading on the 'with' keyword, I'm down to:

    Code:
    #### imports:
    import sys
    
    file = sys.argv[1]
    
    try:
       with open(file) as fo:
          lines = fo.readlines()
    except IOError as e:
       print "Can't open file:", e
       sys.exit(1)
       
    print 'you made it this far!'
    The idea of pre-initializing the variable is quite clever. Wish I'd thought of that myself!

    Thanks again.

    Doug O'Leary

IMN logo majestic logo threadwatch logo seochat tools logo