Reputation: 324
Following Jean's answer to my question on: Python converting strings in a list to numbers , I get a StopIteration
exception when running the below minimal code.
primes
and z2
are empty.
From googling I think I may need a while loop around the line in traceback but I'm not sure how to remedy?
Traceback:
File "factorise_v32.py", line 118, in factorise
primes=[next(z2) for _ in xrange(b)]
StopIteration
Sample data in CSV file:
("2","3","5","7","11")
Minimal Code:
import csv
def factorise(N)
....
z1=(int(x) for row in csv.reader(csvfile) for x in row)
....
b=4 #b can be any positive integer
z2=(int(x) for row in csv.reader(csvfile) for x in row)
primes=[next(z2) for _ in xrange(b)]
Upvotes: 1
Views: 1912
Reputation: 1121644
A list comprehension is not a generator or iterator itself. It will not stop when the expression side raises a StopIteration
exception. The iterable that for ... in <iterable>
loops over can use StopIteration
to communicate to the for
loop that iteration is done, but that doesn't extend to the rest of the construct.
If you need to get at most b
number of elements from an iterator, use itertools.islice()
:
primes = list(islice(z2, b))
It'll take up to b
elements when iterated over, or less if there are not enough elements in z2
.
An earlier revision of the post you linked to tried to pad out the result with 0
values in case there were fewer than b
elements by giving next()
a default value. I'd have used itertools.repeat()
and itertools.chain()
to achieve this:
primes = list(islice(chain(z2, repeat(0)), b))
The chain(z2, repeat(0))
part will endlessly add 0
values after z2
is exhausted. islice()
takes b
elements from that sequence.
Demo:
>>> from itertools import chain, repeat, islice
>>> z2 = iter([1, 2, 3])
>>> list(islice(z2, 5)) # up to 5
[1, 2, 3]
>>> z2 = iter([1, 2, 3]) # pad with zeros
>>> list(islice(chain(z2, repeat(0)), 5))
[1, 2, 3, 0, 0]
Note that you can't read from a CSV file twice in a row, not without rewinding the file object first. Your code is using csv.reader(csvfile)
in two locations, but the csvfile
file object does not go back to the start. Add csvfile.seek(0)
before trying to read from it again.
Upvotes: 2