Reputation: 147
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
Upvotes: 9
Views: 3044
Reputation:
strong text
def text_lines(path):
textFile = open(path, "r")
while True:
line = textFile.readline()
if line :
yield line.strip()
else:
break
textFile.close()
Upvotes: 0
Reputation: 103694
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
Upvotes: 9
Reputation: 10409
You get StopIteration on the second next() because you've only yielded one result. Did you mean to do this instead?
def file_gen(f_name):
f = open(f_name)
lines = f.readlines()
for line in lines:
yield line
Upvotes: 2
Reputation: 259
doesn't
line = f.readline()
only give you one line to yield? therefore iteration stops after that...
Upvotes: 1