The most effective way is to use the properties of the exponential function.
exp(x)=(exp(x/N))^N
Thus you compute x=exp(2^(-n)) with 2n bits more precision than required in the final result, and compute e by squaring the result n times.
For small numbers x, the error of truncating the series for exp(x) at the term with power m-1 is smaller than two times the next term with power m.
To summarize, to compute e with a precision/accuracy of d bit, you select some medium large n and select m such that
2^(1-mn)/m! is smaller than 2^(-d-2n)
This determination of m can also be done dynamically (using Decimal as in the answer of user22698)
from decimal import Decimal, getcontext
def eulernumber(d):
dd=d
n=4
while dd > 1:
dd /= 8
n += 1
getcontext().prec = d+n
x = Decimal(1)/Decimal(1 << n)
eps = Decimal(1)/Decimal(1 << (1 + (10*d)/3 ))
term = x
expsum = Decimal(1) + x
m = 2
while term > eps:
term *= x / Decimal(m)
m += 1
expsum += term
for k in range(n):
expsum *= expsum
getcontext().prec = d
expsum += Decimal(0)
return expsum
if __name__ == "__main__":
for k in range(1,6):
print(k,eulernumber(4*k))
for k in range(10,13):
print(k,eulernumber(4*k))
with output
( 1, Decimal('2.718'))
( 2, Decimal('2.7182818'))
( 3, Decimal('2.71828182846'))
( 4, Decimal('2.718281828459045'))
( 5, Decimal('2.7182818284590452354'))
(10, Decimal('2.718281828459045235360287471352662497757'))
(11, Decimal('2.7182818284590452353602874713526624977572471'))
(12, Decimal('2.71828182845904523536028747135266249775724709370'))
See the (unix/posix) bc math library for a more professional implementation of this idea, also for the logarithm and trig functions. The code of the exponential function is even given as example in the man page.