在Python 2.6中不推荐使用BaseException.message

当我使用以下用户定义的exception时,我得到一个警告,提示在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 

这有什么问题? 为了摆脱弃用警告,我需要做些什么改变?

解决scheme – 几乎不需要编码

只需从Exceptioninheritanceexception类,并将消息作为第一个parameter passing给构造函数

例:

 class MyException(Exception): """My documentation""" try: raise MyException('my detailed description') except MyException as my: print my # outputs 'my detailed description' 

你可以使用str(my)或(less) my.args[0]来访问自定义消息。

背景

在较新版本的Python(从2.6开始)中,我们应该从Exception(inheritance自Python 2.5 )从BaseExceptioninheritance我们的自定义exception类。 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__已经以有意义的方式实现了,特别是对于只有一个参数(可以用作消息)的情况。

您不需要重复__str____init__实现或创build其他人build议的_get_message

是的,它在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) 

希望这可以帮助

 class MyException(Exception): def __str__(self): return repr(self.args[0]) e = MyException('asdf') print e 

这是您的Python2.6风格的类。 新的exception需要任意数量的参数。

据我可以告诉,简单地使用不同的消息属性名称避免与基类的冲突,从而停止弃用警告:

 class MyException(Exception): def __init__(self, message): self.msg = message def __str__(self): return repr(self.msg) 

对我来说似乎是一个黑客。

也许有人可以解释为什么即使在子类明确定义了一个消息属性的时候也会发出这个警告。 如果基类不再具有此属性,则不应该有问题。

如何复制警告

让我来澄清这个问题,因为不能用问题的示例代码复制这个问题,这将会复制警告:

 >>> error = Exception('foobarbaz') >>> error.message __main__:1: DeprecationWarning: BaseException.message has been deprecated as of Python 2.6 'foobarbaz' 

在仍然使用.message同时消除警告

摆脱 DeprecationWarning是按照Pythondevise人员的意图划分内置的exception:

 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属性

但是,可能最好避免使用message属性,而只是采取错误的大小。 只是子类Exception

 class MyException(Exception): '''demo straight subclass''' 

和用法:

 >>> myexception = MyException('my message') >>> str(myexception) 'my message' 

另请参阅此答案:

在现代Python中声明自定义exception的正确方法是什么?

从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) 

有时exception有多个参数,所以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 

使用str(myexception)的build议会导致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'δσφφδσ')) 

按预期工作,并且在错误string的一些内容包括用户input的情况下是优选的

pzrq的post说使用:

 str(e) 

这正是我所需要的。

(如果您处于unicode环境,则显示:

 unicode(e) 

会起作用,而且在非Unicode的环境下似乎也能正常工作)

Pzrq说了很多其他的好东西,但由于所有的好东西,我几乎错过了他们的答案。 由于我没有50分,我不能评论他们的答案,试图提请注意简单的解决scheme,因为我没有15,我不能投票答复,但我可以后(感到落后,但哦) – 所以我在这里发布 – 可能会失去点…

因为我的观点是要引起人们对pzrq答案的关注,所以请不要鄙视下面的内容。 这篇文章的前几行是最重要的。

我的故事:

我来这里的问题是,如果你想从一个你无法控制的类捕捉exception – 那么? 我当然不会将我的代码使用的所有可能的类子类化,以试图从所有可能的exception中获取消息!

我正在使用:

 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时不好,但是希望能够处理意想不到的例外(*)没有死亡,仍然从它得到一些信息将永远不会消失…

(*)嗯。 “意外的例外” – 我想我只是结结巴巴!