user1148257
user1148257

Reputation: 237

Nesting "for" loop within a "try" operator

Folks,

I've resigned myself to working around this problem, but I wanted to check if Python is really acting as expected.

In the example, "sample.txt" is any multi-line text file that is read and parsed.

try:
    file=open('sample.txt','r')
    for line in file:
          (some action here)
except:
    print "Couldn't open file"
file.close()

The actions I observe are that "sample.txt" is opened and the first line handled, the logic then falls through to the "except" clause.

WAD or is this a bug?

Upvotes: 1

Views: 15010

Answers (6)

Makoto
Makoto

Reputation: 106410

The actions I observe are that "sample.txt" is opened and the first line handled, the logic then falls through to the "except" clause.

Yes, this is the case. But this only occurs as long as the file exists.

As for the error falling through to the except clause (assuming the file exists), that implies that there is an issue with the parsing logic you've implemented. We can't be sure what it is since the except catches everything, and unless it's re-raised (may as well not catch it then...), or you print the stack trace from the exception object, you can't tell what is going wrong or where. In general, this is why catching everything is frowned upon; it makes debugging unnecessarily difficult.

I also noticed that you are closing the file at the very end. This is probably another source of errors, since the file only exists within the scope of try. You have two options:

  1. Include file.close() inside of your try block so the file is properly closed after you're done, or
  2. Use the with statement as a context manager to automatically close the file when you're done. @David Heffernan's example is one that's similar to one I would write.

Upvotes: 0

Justin.Wood
Justin.Wood

Reputation: 715

Try using readlines to generate a list of all lines in the file. And you also shouldnt be catching general errors without at least printing the error code.

try:
    file=open('sample.txt','r')
    for line in file.readlines():
          (some action here)
except Exception, e:
    print str(e)
file.close()

Upvotes: 0

Chris AtLee
Chris AtLee

Reputation: 8066

your code risks raising another assertion trying to close file if for some reason the open() call fails. This is because the file variable won't be set if open() raises an exception, and so your call further down will reference a variable that doesn't exist.

If possible, try using the with statement:

with open('sample.txt', 'r') as file:
    try:
        for line in file:
            (some action)
    except:
        print "Exception"
        import traceback; traceback.print_exc()

This will make sure that file is closed afterwards regardless of what happens inside the with statement.

Upvotes: 1

David Heffernan
David Heffernan

Reputation: 612914

If the code in the except block runs it is because an exception was raised. You swallow the exception which makes it hard to know what's going wrong.

Your error message suggests that you are attempting to trap errors raised in the file open. But since your try block surrounds the entire processing of the file, exceptions raised in the processing, as opposed to the file open, will be mis-reported as "Could not open file". If you really must handle the exception then you need to move the for loop to be after the except block.

Personally I'd be inclined to simply ignore the exception and let the default handling of the exception halt execution:

with open('sample.txt','r') as file:
    for line in file:
        (some action here)

If you must handle the exception then be discerning about the class exception that you handle. For example, handle just IOError since that is what open raises in case of failure.

try:   
    with open('sample.txt','r') as file:
        for line in file:
            (some action here)
except IOError:
    except IOError as (errno, strerror):
        print "I/O error({0}): {1}".format(errno, strerror)

Upvotes: 6

Kirk Strauser
Kirk Strauser

Reputation: 30937

That bare except catches all exceptions, including ones in the (some action here) part. Restructure that as:

try:
    inputfile = open('sample.txt', 'r')
except:
    print "Couldn't open file"
else:
    for line in inputfile: pass
    inputfile.close()

Or even better:

with open('sample.txt', 'r') as inputfile:
    for line in inputfile: pass

In general, only wrap the bare minimum amount of code possible inside a try block so that you're not accidentally handling exceptions you're not really prepared to deal with.

Upvotes: 3

Claudiu
Claudiu

Reputation: 229331

It's not failing on the open line, then. What's the exception?

try:
    file=open('sample.txt','r')
    for line in file:
          (some action here)
except:
    print "Exception:"
    import traceback; traceback.print_exc()

file.close()

Upvotes: 3

Related Questions