def sieve_of_eratosthenes(p_min=2, p_max=None):

    """ Generator of prime numbers using the sieve of Eratosthenes.

    Note:
        Adapted from http://code.activestate.com/recipes/117119/

    Args:
        p_min (int): prime numbers lower than p_min will not be in the resulting primes
        p_max (int): the generator will stop when this value is reached, it means that there
            will be no prime bigger than this number in the resulting primes. If p_max
            is None, there will not be any upper limit

    Returns:
        A generator of all the consecutive primes between p_min and p_max

    Raises:
        TypeError: if p_min or p_max is not an integer

    """

    if not isinstance(p_min, int):
        raise TypeError("Expecting an integer")
    if p_max is not None and not isinstance(p_max, int):
        raise TypeError("Expecting an integer")

    sieve = {}
    q = 2

    while p_max is None or q <= p_max:
        if q not in sieve:
            if q >= p_min:
                yield q
            sieve[q * q] = [q]
        else:
            for p in sieve[q]:
                sieve.setdefault(p + q, []).append(p)
            del sieve[q]

        q += 1
Generator of prime numbers using the sieve of Eratosthenes.

    Note:
        Adapted from http://code.activestate.com/recipes/117119/

    Args:
        p_min (int): prime numbers lower than p_min will not be in the resulting primes
        p_max (int): the generator will stop when this value is reached, it means that there
            will be no prime bigger than this number in the resulting primes. If p_max
            is None, there will not be any upper limit

    Returns:
        A generator of all the consecutive primes between p_min and p_max

    Raises:
        TypeError: if p_min or p_max is not an integer