问题:Python 2.6中不推荐使用BaseException.message
当我使用以下用户定义的异常时,我收到一条警告:Python 2.6中不推荐使用BaseException.message:
class MyException(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return repr(self.message)
这是警告:
DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
self.message = message
这怎么了 我要更改什么以摆脱过时警告?
回答 0
解决方案-几乎不需要编码
只是继承您的异常类,Exception
并将消息作为第一个参数传递给构造函数
例:
class MyException(Exception):
"""My documentation"""
try:
raise MyException('my detailed description')
except MyException as my:
print my # outputs 'my detailed description'
您可以使用str(my)
或(不太优雅)my.args[0]
来访问自定义消息。
背景
在较新的Python版本(从2.6开始)中,我们应该从Exception(从Python 2.5开始)继承自BaseException的自定义异常类中继承。在PEP 352中详细描述了背景。
class BaseException(object):
"""Superclass representing the base of the exception hierarchy.
Provides an 'args' attribute that contains all arguments passed
to the constructor. Suggested practice, though, is that only a
single string argument be passed to the constructor."""
__str__
并且__repr__
已经以有意义的方式实现,尤其是对于仅一个arg(可用作消息)的情况。
您无需重复__str__
或__init__
实施或创建_get_message
其他人建议的内容。
回答 1
是的,它在Python 2.6中已弃用,因为它在Python 3.0中已经不存在了
BaseException类不再提供存储错误消息的方法。您必须自己实施。您可以使用一个子类来执行此操作,该子类使用用于存储消息的属性。
class MyException(Exception):
def _get_message(self):
return self._message
def _set_message(self, message):
self._message = message
message = property(_get_message, _set_message)
希望这可以帮助
回答 2
class MyException(Exception):
def __str__(self):
return repr(self.args[0])
e = MyException('asdf')
print e
这是您使用Python2.6样式的类。新的异常采用任意数量的参数。
回答 3
如何复制警告
让我澄清一下问题,因为您无法使用问题的示例代码来复制此问题,如果您启用了警告(通过-W
flag,PYTHONWARNINGS
environment变量或warnings模块),则会在Python 2.6和2.7中复制警告:
>>> error = Exception('foobarbaz')
>>> error.message
__main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6
'foobarbaz'
停止使用 .message
我更喜欢使用repr(error)
,它返回一个字符串,其中包含错误类型的名称,消息的repr(如果有的话)以及其余参数的repr。
>>> repr(error)
"Exception('foobarbaz',)"
仍在使用时消除警告 .message
你得到的方式干掉的DeprecationWarning
是继承一个内置的exceptions,因为Python的设计意图:
class MyException(Exception):
def __init__(self, message, *args):
self.message = message
# delegate the rest of initialization to parent
super(MyException, self).__init__(message, *args)
>>> myexception = MyException('my message')
>>> myexception.message
'my message'
>>> str(myexception)
'my message'
>>> repr(myexception)
"MyException('my message',)"
只获得.message
属性而没有error.message
如果您知道要向Exception发送一个参数,即一条消息,这就是您想要的,那么最好避免使用message属性,而只处理str
错误。说一个子类Exception
:
class MyException(Exception):
'''demo straight subclass'''
和用法:
>>> myexception = MyException('my message')
>>> str(myexception)
'my message'
另请参阅以下答案:
回答 4
据我所知,仅对message属性使用其他名称可以避免与基类发生冲突,从而停止弃用警告:
class MyException(Exception):
def __init__(self, message):
self.msg = message
def __str__(self):
return repr(self.msg)
在我看来就像是骇客。
也许有人可以解释为什么即使子类显式定义了message属性,也会发出警告。如果基类不再具有此属性,则应该没有问题。
回答 5
继续从geekQ的答案开始,首选的代码替换取决于您需要执行的操作:
### Problem
class MyException(Exception):
"""My documentation"""
try:
raise MyException('my detailed description')
except MyException as my:
### Solution 1, fails in Python 2.x if MyException contains 🔥
# with UnicodeEncodeError: 'ascii' codec can't encode characters in position 24-25: ordinal not in range(128)
print(my) # outputs 'my detailed description'
### Solution 2
# Works in Python 2.x if exception only has ASCII characters,
# should always work in Python 3.x
str(my)
### Solution 3
# Required in Python 2.x if you need to handle non-ASCII characters,
# such as δσφφδσ (as pointed out by jjc) or emoji 🔥 💕 🎁 💯 🌹
# but does not work in Python 3.x
unicode(my)
有时,异常包含多个参数,因此my.args[0]
不能保证提供所有相关信息。
例如:
# Python 2.7
try:
u'\u12345'.encode('utf-8').encode('utf-8')
except UnicodeDecodeError as e:
print e.args[0]
print e.args
print str(e)
打印为输出:
ascii
('ascii', '\xe1\x88\xb45', 0, 1, 'ordinal not in range(128)')
'ascii' codec can't decode byte 0xe1 in position 0: ordinal not in range(128)
但是,这是上下文相关的折衷,因为例如:
# Python 2.7
>>> str(SyntaxError())
'None'
# 'None' compares True which might not be expected
回答 6
使用str(myexception)的建议会导致python 2.7中的unicode问题,例如:
str(Exception(u'δσφφδσ'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
:(
unicode(Exception(u'δσφφδσ'))
可以按预期工作,并且在错误字符串的某些内容包括用户输入的情况下更可取
回答 7
pzrq的帖子说使用:
str(e)
这正是我所需要的。
(如果您在unicode环境中,则似乎:
unicode(e)
可以正常工作,并且在非Unicode环境中似乎可以正常工作)
Pzrq说了很多其他好东西,但是由于所有好东西,我几乎都错过了他们的答案。由于我没有50分,因此我无法就他们的答案发表评论,以引起人们对有效的简单解决方案的关注;由于我没有15分,因此我无法投票赞成该答案,但是我可以发表评论(感觉是倒退的,但是哦,好)-我在这里发布-可能会因此而失去积分…
由于我的意思是要引起人们对pzrq答案的关注,请不要着迷并在下面的所有内容中忽略它。这篇文章的前几行是最重要的。
我的故事:
我来到这里的问题是,如果您想从无法控制的类中捕获异常,那么该怎么办?我当然不会继承我的代码使用的所有可能的类,以试图从所有可能的异常中获取消息!
我正在使用:
except Exception as e:
print '%s (%s)' % (e.message,type(e))
正如我们现在所知道的那样,它给出了警告OP的警告(这将我带到了这里),而这就是pzrq给出的一种解决方法:
except Exception as e:
print '%s (%s)' % (str(e),type(e))
没有。
我不是在unicode环境中,但是jjc的回答让我感到疑惑,因此我不得不尝试一下。在这种情况下,它将变为:
except Exception as e:
print '%s (%s)' % (unicode(e),type(e))
令我惊讶的是,它的工作原理与str(e)完全一样-所以现在这就是我正在使用的。
不知道’str(e)/ unicode(e)’是否是’认可的Python方式’,我很可能会发现为什么当我达到3.0时这不好,但是有人希望能够处理不会死的意外异常(*)永远不会消失…
(*)嗯。“意外异常”-我想我口吃了!