Writing a Pythonic prime sieve
Your implementation of the sieve, using a dictionary, throws away many of the benefits of the approach; dictionaries are unordered. Even a naive list-based implementation ends up processing fewer than half as many numbers (146 vs. 382 with a limit of 100):

def sieve(limit):
    nums = range(limit+1)
    nums[1] = 0
    for n in nums:
        if n:
            for x in range(2*n, limit+1, n):
                nums[x] = 0 # counting this vs. pop
    return set(filter(None, primes))


Your approach processes multiples of numbers that will subsequently turn out to be non-prime themselves, e.g. you might pop all multiples of 9, then go back over them when you later process 3.

Note that I have used a set, which is effectively a dictionary with no values, rather than have some dummy value. 

Also, there was no need to copy the whole dictionary; for n in numbers.keys() would have worked fine. 

There are numerous other implementations, in Python and other languages, on this site and elsewhere; I suggest you look at a few to see what other alterations could be made.