This code below works correct :
JavaScript
x
10
10
1
def file_gen(f_name):
2
f = open(f_name)
3
for line in f:
4
yield line
5
6
gen_line = file_gen("foo.html")
7
gen_line.next() # '<!DOCTYPE>n'
8
gen_line.next() # '<html> n'
9
gen_line.next() # ... next line in file
10
But this function raises StopIteration
. I don’t understand why ?
JavaScript
1
9
1
def file_gen(f_name):
2
f = open(f_name)
3
line = f.readline()
4
yield line
5
6
gen_line = file_gen('foo.html')
7
gen_line.next() # '<!DOCTYPE>n'
8
gen_line.next() # StopIteration
9
Advertisement
Answer
You have:
JavaScript
1
5
1
def file_gen(f_name):
2
f = open(f_name)
3
line = f.readline()
4
yield line
5
Notice line = f.readline()
This only reads 1 line from the file.
Compare:
JavaScript
1
7
1
def g(x):
2
li=range(x)
3
yield li.pop()
4
5
print list(g(10))
6
# [9]
7
with this:
JavaScript
1
8
1
def g(x):
2
li=range(x)
3
while li:
4
yield li.pop()
5
6
print list(g(10))
7
# [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
8
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:
JavaScript
1
8
1
def file_gen(f_name):
2
f = open(f_name)
3
while True:
4
line = f.readline()
5
if not line:
6
break
7
yield line
8
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:
JavaScript
1
5
1
def file_gen(f_name):
2
with open(f_name) as f:
3
for line in f:
4
yield line
5