python - 异常 str() 失败 - py3
问题描述
这在 Py2 中工作正常,但在 Py3 中失败
import sys
class MyBaseError(Exception):
def __init__(self, message, base_message=None, *args):
self.base_message = base_message
super(MyBaseError, self).__init__(message)
def __str__(self):
if self.base_message is None:
return self.message
return self.message + " '" + str(self.base_message) + "'"
class MyError(MyBaseError):
"""
"""
class MyTypeError(MyError):
"""
"""
def run_me():
raise MyTypeError("run_me")
def sayonara():
try:
run_me()
except (MyBaseError) as e:
raise(MyBaseError("unable to run",
e,
e.args),
sys.exc_info()[2])
sayonara()
在 Py2 我得到
Traceback (most recent call last):
File "main.py", line 39, in <module>
sayonara()
File "main.py", line 37, in sayonara
sys.exc_info()[2])
__main__.MyBaseError: unable to run 'run_me'
在 Py3 我得到
Traceback (most recent call last):
File "main.py", line 32, in sayonara
run_me()
File "main.py", line 27, in run_me
raise MyTypeError("run_me")
__main__.MyTypeError: <exception str() failed>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "main.py", line 42, in <module>
sayonara()
File "main.py", line 34, in sayonara
print(e)
File "main.py", line 13, in __str__
return self.message
AttributeError: 'MyTypeError' object has no attribute 'message'
你能建议我怎么做这个多语种吗?
解决方案
__str__
您在 MyBaseError 中定义的实例方法的覆盖实现引用了不存在的实例变量。 message
在构造函数的签名中声明的参数message
具有本地范围。
当您将字符串等不可变参数传递给函数时,会传递参数的值。在MyBaseError
您的构造函数中,将局部变量的值传递message
给代理对象的__init__
方法,代理对象将方法调用委托给父类Exception
。
在 python3 中,Exception
没有定义一个实例变量message
来保存实例参数的字符串表示形式。这就是导致异常的原因。
此外,如果您解决了该问题,您将收到类型错误:
TypeError: exceptions must derive from BaseException
那是因为你写的 raise 语句不符合 Python 3 中 raise 语句的语义。 raise 语句的 BNF 如下所示:
raise_stmt ::= "raise" [expression ["from" expression]]
正如语言参考所述:'raise 将第一个表达式评估为异常对象。它必须是 BaseException 的子类或实例。
但是,在您的 raise 语句中,第一个表达式是一个元组:
(MyBaseError("unable to run", e, e.args), sys.exc_info()[2])
(https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement)。
要修复您的代码,请创建message
一个实例变量并重构 raise 语句。
import sys
class MyBaseError(Exception):
def __init__(self, message, base_message=None, *args):
self.base_message = base_message
self.message = message
def __str__(self):
if self.base_message is None:
return self.message
return self.message + " '" + str(self.base_message) + "'"
class MyError(MyBaseError):
"""
"""
class MyTypeError(MyError):
"""
"""
def run_me():
raise MyTypeError("run_me")
def sayonara():
try:
run_me()
except (MyBaseError) as e:
raise MyBaseError("unable to run", e, e.args)
sayonara()
此外,以下语句从您的代码中返回一个回溯对象。
sys.exc_info()[2]
正如语言参考所述:“当引发异常并将其作为可写的回溯属性附加到它时,通常会自动创建回溯对象。” 如果您愿意,您可以使用 with_traceback() 异常方法一步设置您自己的自定义回溯。
推荐阅读
- python-3.x - 为什么 while 循环不会停止并且 .write() 不起作用?蟒蛇3
- bash - Circle CI 的 docker-compose 部署配置
- python - 如何将具有两个变量的字符串数组放入文本文件中?
- google-tag-manager - 如何从 GTM 自定义标签模板发送 POST 请求?
- python - SMOTE 函数在 make_pipeline 中不起作用
- vuejs2 - 为什么我的嵌套组件不渲染?
- java - TCP服务器接受连接后的新线程代码未执行
- javascript - JSON.stringify() 与 array.join(',')
- python - 搜索特定单词的用户输入
- python - 为列和行的某些子集将列转换为行?