When you say "name" this could mean a couple of things: it could mean only the "immediate" classname, or it could mean the fully qualified name. Usually the latter will be much more useful and less error-prone: I've come across more than one case of 2 or more types with same "immediate" classname but from different packages.
If you want to print or log the fully qualified name this is one of the simplest things to do:
try: do_something() except BaseException as e: logger.error(f'whoops! {type(e)}: {e}') # or maybe print(f'whoops! {type(e)}: {e}', file=sys.stderr)
The fully qualified classname will then be printed out like this: "<class 'json.decoder.JSONDecodeError'>", and then be followed by the exception message. The OP says he wants "for example", to print a message, so assert statements as in the chosen answer don't seem to be called for.
The answer by MrName is also not irrelevant, and does make a sensible suggestion! if in the above you replaced logger.error(...) with logger.exception('whoops!') (NB a user message is a required param) you'd get your exception's fully qualified name logged, not to mention its message, and a stack trace for free.
PS as suggested by the name, JSONDecodeError in my example is an Error, not an Exception (it is a subclass of ValueError). Catching BaseException (the superclass of both Error and Exception) usually makes life easier when you're not fishing for a specific exception. The OP says he wants to catch "all" exceptions.
except NameError:) to begin with?tracebackmodule, which has functions that do some nice formatting of exceptions and tracebacks.exceptstatement, but the log entry is very similar in each case.