There is a cleaner way to handle your situation: you have a data source consisting of paged data, but the termination condition can be detected by examining individual rows. So I would use an iterator that retrieves the data row by row and stops when necessary. No special values (in or out of range), no two-way communication.
Edit: I just found that you really don't care about page borders. In this case, you should simply use this:
def linegetter(url_template): """ Return the data line by line. Stop when end of input is detected. """ n=0 while True: n += 1 data = json.load(urlopen(url_template % n)) if data is None: return for row in data: if row_is_weird(row): return yield row
It returns data line by line, and you can prepare and consume it in any way. Done!
That should be the whole answer, it seems. But suppose you need to process the data page by page (as your code does). Just group the first iterator output into sub iterators for each page. The code is more complicated because I inserted it into a completely general solution; but using it is very simple.
def linegetter(source, terminate=lambda x: False): """ Return the data line by line, in a tuple with the page number. Stop when end of input is detected. """ for n, data in enumerate(source): if data is None: return for row in data: if terminate(row): return yield (n, row) def _giverow(source): "Yield page contents line by line, discarding page number" for page, row in source: yield row def pagegetter(source): """Return an iterator for each page of incoming data. """ import itertools for it in itertools.groupby(source, lambda x : x[0]): yield _giverow(it[1])
Demo: Each "line" is a number, each page is a sublist. We stop when we see "b". There are no final checks in your main loop:
incoming = iter([[1,2,3], [4,5,6, "b", 7], [7,8,9]]) def row_is_weird(r): return r == "b" for page in pagegetter(linegetter(incoming, row_is_weird)): print list(page)
As you can see, the code is completely general. You can use it with an iterator that retrieves json pages, for example:
from itertools import imap, count jsonsource = imap(lambda n: json.load(urlopen(url_template % n)), count(1)) for page in pagegetter(linegetter(jsonsource, row_is_weird)): consume(page)