This code below works correct :
def file_gen(f_name): f = open(f_name) for line in f: yield line gen_line = file_gen("foo.html") gen_line.next() # '<!DOCTYPE>n' gen_line.next() # '<html> n' gen_line.next() # ... next line in file
But this function raises StopIteration
. I don’t understand why ?
def file_gen(f_name): f = open(f_name) line = f.readline() yield line gen_line = file_gen('foo.html') gen_line.next() # '<!DOCTYPE>n' gen_line.next() # StopIteration
Advertisement
Answer
You have:
def file_gen(f_name): f = open(f_name) line = f.readline() yield line
Notice line = f.readline()
This only reads 1 line from the file.
Compare:
def g(x): li=range(x) yield li.pop() print list(g(10)) # [9]
with this:
def g(x): li=range(x) while li: yield li.pop() print list(g(10)) # [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
yield
can only be called once with a particular object or expression. Once it is used by the receiver it must be regenerated. So you need a loop around reading each line of the file.
You can use your second (less readable) form this way:
def file_gen(f_name): f = open(f_name) while True: line = f.readline() if not line: break yield line
You need a loop to create the the items to yield. In your first case, for line in f: yield line
is a loop.
I would rewrite your function this way:
def file_gen(f_name): with open(f_name) as f: for line in f: yield line