# from:  http://r...content-available-to-author-only...e.org/wiki/Sieve_of_Eratosthenes#Infinite_generator_with_a_faster_algorithm

def primes():
    yield 2; yield 3; yield 5; yield 7;
    bps = (p for p in primes())             # additional primes supply
    p = next(bps) and next(bps)             # discard 2, then get 3
    q = p * p                               # 9 - square of next prime to be put
    sieve = {}                              #       into sieve dict
    n = 9                                   # the initial candidate number
    while True:
        if n not in sieve:                  # is not a multiple of previously recorded primes
            if n < q:
                yield n                     # n is prime
            else:
                p2 = p + p                  # n == p * p: for prime p, add p * p + 2 * p,
                sieve[q + p2] = p2          #               with 2 * p as incremental step
                p = next(bps); q = p * p    # advance base prime and next prime to be put                
        else:
            s = sieve.pop(n); nxt = n + s   # n is composite, advance
            while nxt in sieve: nxt += s    # ensure each entry is unique
            sieve[nxt] = s                  # next non-marked multiple of this prime
        n += 2                              # work on odds only

ps = primes()                               # 100k: 0.72s-9.4MB
for n in range(1, 1000000): next(ps)        # 200k: 1.51s-9.4MB   n^1.07 !!
print(next(ps))                             # 400k: 3.23s-9.4MB   n^1.10 !!!
                                            # 1m:   8.63s-9.4MB   n^1.07 !!!   15485863