python 中的e.message

最近发现还有人在处理Exception的时候还在使用e.message来输出异常(错误)信息。

程序中的一个举例(日志):

[E 170831 21:24:33 handler:199] [CRP] Get azuop_hypervisors_statistics err: ('list index out of range',)
    Traceback (most recent call last):
      File "/opt/crp-backend/crp/availability_zone/handler.py", line 175, in get
        hosts = zones[0].hosts.keys()
    IndexError: list index out of range
/opt/crp-backend/crp/availability_zone/handler.py:205: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
  "msg": e.message
[W 170831 21:24:33 wsgi:355] 400 GET /api/az/uopStatistics (172.28.26.199) 1434.54ms

现在Python的最新版本已经是 python2.7.13/python3.6.2, 而 e.message 则是python2.5.x 的语法了。

推荐的写法是:

  1. e.message 改为 e.args

返回一个tuple, 如果信息为空,则返回一空的tuple, ()

  1. 自定义Exception,实现 message 的属性。

使用交互式命令行的一个调试:


$ ipython
Python 2.7.5 (default, Nov  6 2016, 00:28:07)
Type "copyright", "credits" or "license" for more information.

IPython 5.0.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: error = Exception('foobarbaz')

In [2]: error.message
/bin/ipython:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
  #!/usr/bin/python
Out[2]: 'foobarbaz'

In [3]: error.args
Out[3]: ('foobarbaz',)

In [4]: error = Exception()

In [5]: error.message
/bin/ipython:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
  #!/usr/bin/python
Out[5]: ''

In [6]: error.args
Out[6]: ()

扩展阅读

PEP 352 -- Required Superclass for Exceptions
https://www.python.org/dev/peps/pep-0352/
简介:

Here is BaseException as implemented in the 2.x series:

class BaseException(object):

    """Superclass representing the base of the exception hierarchy.

    The __getitem__ method is provided for backwards-compatibility
    and will be deprecated at some point.  The 'message' attribute
    is also deprecated.

    """

    def __init__(self, *args):
        self.args = args

    def __str__(self):
        return str(self.args[0]
                   if len(self.args) <= 1
                   else self.args)

    def __repr__(self):
        func_args = repr(self.args) if self.args else "()"
        return self.__class__.__name__ + func_args

    def __getitem__(self, index):
        """Index into arguments passed in during instantiation.

        Provided for backwards-compatibility and will be
        deprecated.

        """
        return self.args[index]

    def _get_message(self):
        """Method for 'message' property."""
        warnings.warn("the 'message' attribute has been deprecated "
                        "since Python 2.6")
        return self.args[0] if len(args) == 1 else ''

    message = property(_get_message,
                        doc="access the 'message' attribute; "
                            "deprecated and provided only for "
                            "backwards-compatibility")

Deprecation of features in Python 2.9 is optional. This is because it is not known at this time if Python 2.9 (which is slated to be the last version in the 2.x series) will actively deprecate features that will not be in 3.0. It is conceivable that no deprecation warnings will be used in 2.9 since there could be such a difference between 2.9 and 3.0 that it would make 2.9 too "noisy" in terms of warnings. Thus the proposed deprecation warnings for Python 2.9 will be revisited when development of that version begins, to determine if they are still desired.

DeprecationWarning: BaseException.message has been deprecated as of Python 2.6 exception.class, exception.message,
https://stackoverflow.com/questions/13063212/deprecationwarning-baseexception-message-has-been-deprecated-as-of-python-2-6-e

简介:

If I remember correctly, when Python switched to the new raise syntax in 2.5(?), they got rid of the message member in favor of an args tuple. For backward compatibility, BaseException.message is effectively the same thing as BaseException.args[0] if BaseException.args else None, but you shouldn't use it in new code.

So, change message to either args (if you want all args) or args[0] (or, if you're worried there may be no args, the fancier version that protects against ()), depending on which you want.

The reason for this change is that with the new-style exceptions, there's no magic to raise or except anymore; you're just calling the exception class's constructor in the raise statement, and catching the exception in a variable in the except statement. So:

try:
  raise MyException('Out of cheese error', 42)
except Exception as x:
  print x.args
This will print ('Out of cheese error', 42). If you only had print x.message you'd just get 'Out of cheese error'. So, the Exception subclasses that used to have to do fancy things to carry around an error code as a separate member, etc., can be simplified; in fact, the whole thing comes down to this:

class BaseException(object):
  def __init__(self, *args):
    self.args = args

Proper way to declare custom exceptions in modern Python?
https://stackoverflow.com/questions/1319615/proper-way-to-declare-custom-exceptions-in-modern-python/26938914#26938914

BaseException.message deprecated in Python 2.6

你可能感兴趣的:(python 中的e.message)