In addition to toolic's answer:
List comprehension
primes = []
for i in range(2, lim + 1, 1):
primes.append(i)
could be written simpler (and faster) as:
primes = [i for i in range(2, lim + 1)]
Early termination
Consider this loop:
for i in range(2, lim):
if i*p not in primes:
continue
primes.remove(i*p)
You attempting to eliminating lim multiples of p from a list which can only ever contain numbers up to lim. For instance, with lim = 10, you'll eventually try to remove 2*7, 3*7, 4*7, 5*7, 6*7, 7*7, 8*7, and 9*7. All of those values exceed 10, so none of them could ever be in the list!
Instead, you could stop when i*p exceeds lim. Instead of adding in an extra condition to test this, let's change the loop to stop at that point:
for ip in range(2*p, lim + 1, p):
if ip in primes:
primes.remove(ip)
Now the loop runs from 2*p, and increments by p each time, stopping when it exceeds lim.
Early termination (part 2)
for n in range(lim):
p = primes[0]
try:
p = primes[n]
except IndexError:
pass
for ip in range(2*p, lim + 1, p):
if ip in primes:
primes.remove(ip)
What is happening when you get an IndexError?
It means n is beyond the end of the primes[] list. What will happen in subsequent loops? n will be larger, so same thing. We can abandon further loopping at this point.
try:
for n in range(lim):
p = primes[n]
for ip in range(2*p, lim + 1, p):
if ip in primes:
primes.remove(ip)
except IndexError:
pass
Alternately, you can change the to a while n < len(primes):, and increment n yourself.
Algorithmic Improvements
You don't need to check all multiples of p. Instead of starting at 2*p, you could start at p*p, since you'll have already removed the smaller multiples.
See also: the Sieve of Eratosthenes. You'll find plenty of implementations of it here on Code Review.