How to get exception message in Python properly

前端 未结 4 1891
青春惊慌失措
青春惊慌失措 2020-11-27 13:25

What is the best way to get exceptions\' messages from components of standard library in Python?

I noticed that in some cases you can get it via message

相关标签:
4条回答
  • 2020-11-27 13:56

    I had the same problem. I think the best solution is to use log.exception, which will automatically print out stack trace and error message, such as:

    try:
        pass
        log.info('Success')
    except:
        log.exception('Failed')
    
    0 讨论(0)
  • 2020-11-27 14:01

    If you look at the documentation for the built-in errors, you'll see that most Exception classes assign their first argument as a message attribute. Not all of them do though.

    Notably,EnvironmentError (with subclasses IOError and OSError) has a first argument of errno, second of strerror. There is no message... strerror is roughly analogous to what would normally be a message.

    More generally, subclasses of Exception can do whatever they want. They may or may not have a message attribute. Future built-in Exceptions may not have a message attribute. Any Exception subclass imported from third-party libraries or user code may not have a message attribute.

    I think the proper way of handling this is to identify the specific Exception subclasses you want to catch, and then catch only those instead of everything with an except Exception, then utilize whatever attributes that specific subclass defines however you want.

    If you must print something, I think that printing the caught Exception itself is most likely to do what you want, whether it has a message attribute or not.

    You could also check for the message attribute if you wanted, like this, but I wouldn't really suggest it as it just seems messy:

    try:
        pass
    except Exception as e:
        # Just print(e) is cleaner and more likely what you want,
        # but if you insist on printing message specifically whenever possible...
        if hasattr(e, 'message'):
            print(e.message)
        else:
            print(e)
    
    0 讨论(0)
  • 2020-11-27 14:09

    I too had the same problem. Digging into this I found that the Exception class has an args attribute, which captures the arguments that were used to create the exception. If you narrow the exceptions that except will catch to a subset, you should be able to determine how they were constructed, and thus which argument contains the message.

    try:
       # do something that may raise an AuthException
    except AuthException as ex:
       if ex.args[0] == "Authentication Timeout.":
          # handle timeout
       else:
          # generic handling
    
    0 讨论(0)
  • 2020-11-27 14:17

    To improve on the answer provided by @artofwarfare, here is what I consider a neater way to check for the message attribute and print it or print the Exception object as a fallback.

    try:
        pass 
    except Exception as e:
        print getattr(e, 'message', repr(e))
    

    The call to repr is optional, but I find it necessary in some use cases.


    Update #1:

    Following the comment by @MadPhysicist, here's a proof of why the call to repr might be necessary. Try running the following code in your interpreter:

    try:
        raise Exception 
    except Exception as e:
        print(getattr(e, 'message', repr(e)))
        print(getattr(e, 'message', str(e)))
    

    Update #2:

    Here is a demo with specifics for Python 2.7 and 3.5: https://gist.github.com/takwas/3b7a6effffdef783f2abddffda1439f533

    0 讨论(0)
提交回复
热议问题