By doing raise Exception (e), you are creating a new exception, of class Exception, and passing it the old one, e, as its argument. It will convert that argument to a string, so what you end up with is a plain old Exception instance, but with the message from a ZeroDivisionError.
If you want to raise an existing exception, just raise the exception itself:
raise e
However, if you're trying to re-raise the current exception, that's even easier:
raise
To answer your specific question:
My Question is how python decide or choose which exception is occurred,
In general, each function's implementation decides which exception to raise, but there are a few special cases that are explained in the appropriate parts of the language reference.
For your first example, in CPython, the int.__div__ method is implemented in C, but it effectively has code equivalent to this:
def __div__(self, other):
if other == 0:
raise ZeroDivisionError('integer division or modulo by zero')
… do usual division stuff in C …
Your second example is one of those special cases: the implementation of the + operator asks str.__add__ to handle it, and that fails, so it then asks int.__radd__ to handle it, and that also fails, so it gives up and raises a TypeError.
Your third example… well, you explicit wrote raise Exception(e), and that raises an Exception.