简体   繁体   中英

Understanding `traceback.format_exception_only()`

I wanted to just print exception type and message.

I initially tried:

try:
    raise Exception("duh!!!")
except Exception as err:
    print(err)

But this only printed exception message.

 duh!!!

Then I went through the whole traceback doc and I felt traceback.format_exception_only() is the one I am looking for.

So i tried it as follows:

try:
    raise Exception("duh!!!")
except:
    etype, evalue, tb = sys.exc_info()
    print(traceback.format_exception_only(etype, evalue)))

and it printed following:

['Exception: duh!!!\n']

which looked a bit unexpected to me. So I re-read the doc for this method. It says following:

Format the exception part of a traceback. The arguments are the exception type and value such as given by sys.last_type and sys.last_value . The return value is a list of strings, each ending in a newline. Normally, the list contains a single string; however, for SyntaxError exceptions, it contains several lines that (when printed) display detailed information about where the syntax error occurred. The message indicating which exception occurred is the always last string in the list.

So I understood that the doc says its a list, which is why there is a list in the output [...] . Also the doc says each line ends in newline, thats why there is \\n in the output. But I dont get when there will be multiple lines in case of SyntaxError ? I am not able to produce SyntaxError which will result in multiple lines in the return value of format_exception_only() .

Also it suddenly clicked to me that I can simply do

try:
    raise Exception("duh!!!")
except:
    etype, evalue, tb = sys.exc_info()
    print('{}: {}'.format(etype.__name__, evalue))

to get

Exception: duh!!!

But then how format_exception_only() adds more value to this?

Python is open source so you can view the implementation and decide what the extra value is for yourself:

    if self.exc_type is None:
        yield _format_final_exc_line(None, self._str)
        return

    stype = self.exc_type.__qualname__
    smod = self.exc_type.__module__
    if smod not in ("__main__", "builtins"):
        stype = smod + '.' + stype

    if not issubclass(self.exc_type, SyntaxError):
        yield _format_final_exc_line(stype, self._str)
    else:
        yield from self._format_syntax_error(stype)

It's a fairly simple function so yes, per your question if you ignore the parts of the functionality you don't use it doesn't add much value to you.

Of course, you're now on the hook for maintaining your code if there's any Exception changes in the future, or if turns out the Exception raiser starts returning SyntaxErrors, or any other edge cases that come in the future.

Reduced maintenance and increased readability (because everyone knows what the library code does) are the two relatively universal advantages of using standard library code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM