2

I have a text file that I read in with Python and I then determine the line numbers of lines that contain particular keywords. For some reason, I find that I have to open the file each time I search for a different keyword. I've tried using a with statement to keep the file open, but this does not seem to work.

In the example below, I find the line number of the last line in the file as well as the first line that contains the string 'Results'

with open(MyFile,'r') as f:
    lastline = sum(1 for line in f)

    for num, line in enumerate(f): 
        if 'Results' in line:
            ResultLine=num   
            break

This successfully does the first operation (determining the last line), but not the latter. If I instead just open the file twice it works:

f=open(MyFile, 'r')
lastline = sum(1 for line in f)

f=open(MyFile, 'r')      
for num, line in enumerate(f): 
    if 'Results' in line:
        ResultLine=num   
        break

Any suggestions as to why I can't keep the file open with my with statement?

Thanks for the help.

AJG519
  • 3,249
  • 10
  • 36
  • 62

5 Answers5

3

If you want to work with the same file you need to rewind the file pointer. Just do f.seek(0) before your second enumeration

However, getting into what your code is actually doing, it can be optimized to do all in the same loop

with open(MyFile,'r') as f:
    lastline = 0
    ResultLine = None

    for num, line in enumerate(f): 
        if not ResultLine and 'Results' in line:
            ResultLine=num

    lastline = num # + 1 if you want a count; this is what you actually get 
                   # in your sample, the count, not the last line index
Leonid Usov
  • 1,508
  • 12
  • 16
2
with open(MyFile,'r') as f:
    lastline = sum(1 for line in f)

    ## The pointer f has reached the end of the file here
    ## Need to reset pointer back to beginning
    f.seek(0)

    for num, line in enumerate(f): 
        if 'Results' in line:
            ResultLine=num   
            break
csiu
  • 3,159
  • 2
  • 24
  • 26
2

Try doing both tasks together in a single pass over the file:

with open(MyFile,'r') as f:
    searching = True
    for num, line in enumerate(f): 
        if searching and 'Results' in line:
            ResultLine=num
            searching = False
    lastline = num
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97
1

with creates a contextmanager

contextmanagers will automatically clean up after them selves when you exit their scope ... (ie close the filehandle)

this answer only addresses why your filehandle is closed when you exit the with statement

see http://preshing.com/20110920/the-python-with-statement-by-example/ for some more info about the with statement and contextmanagers (first link that came up on googling for "file contextmanager")

Joran Beasley
  • 110,522
  • 12
  • 160
  • 179
-1

The problem is that you've effectively read the entire file once already, so when you go to enumerate the lines, there's nothing left to fetch.

You should read the lines all at once, and evaluate that instead.

f = open(MyFile, 'r')
lines = list(f)

# operate on lines instead of f!
# ...
Colin Basnett
  • 4,052
  • 2
  • 30
  • 49