Вы делаете больше работы, чем необходимо. Вы преобразовали сложение в умножение при просеивании, и начальная и конечная точки просеивания больше, чем необходимо. Вот моя реализация, которая исправляет эти проблемы, а также обрабатывает 2 как особый случай:
def primes(n): # sieve of eratosthenes
i, p, ps, m = 0, 3, [2], n // 2
sieve = [True] * m
while p <= n:
if sieve[i]:
ps.append(p)
for j in range((p*p-3)/2, m, p):
sieve[j] = False
i, p = i+1, p+2
return ps