[英]Exception TypeError warning sometimes shown, sometimes not when using throw method of generator
有这个代码:
class MyException(Exception):
pass
def gen():
for i in range(3):
try:
yield i
except MyException:
print("MyException!")
a = gen()
next(a)
a.throw(MyException)
运行此代码:
$ python3.3 main.py
MyException!
$ python3.3 main.py
MyException!
Exception TypeError: TypeError('catching classes that do not inherit from BaseException is not allowed',) in <generator object gen at 0xb712efa4> ignored
$ python3.3 main.py
MyException!
$ python3.3 main.py
MyException!
$ python3.3 main.py
MyException!
Exception TypeError: TypeError('catching classes that do not inherit from BaseException is not allowed',) in <generator object gen at 0xb714afa4> ignored
我不明白的是为什么有时会打印这个Exception TypeError
警告。 自定义异常有问题吗?
你看到一个__del__
钩子在某个地方行为不端。
在关闭时抛出TypeError
,因为Python解释器退出所有内容都被删除,并且__del__
解构器钩子中抛出的任何异常都被忽略(但是被打印)。
退出时,Python通过将所有内容重新绑定到None
来清除命名空间中的所有内容,但不会设置发生这种情况的顺序。 当被删除时,仍在运行的生成器被关闭( a.close()
被调用),这会在GeneratorExit
中触发GeneratorExit
异常,Python会对你的except MyException:
line进行测试。 但是,如果已经清除MyException
并且Python看到except None:
TypeError
并且您看到该消息已打印。
您可以通过添加以下内容来触发错误而无需退出Python:
MyException = None
del a
如果您使用list(a)
并使用生成器的其余部分,或者在Python退出并删除MyException
之前使用a.close()
显式关闭生成器,则错误消息将消失。
另一个解决方法是首先处理GeneratorExit
:
def gen():
for i in range(3):
try:
yield i
except GeneratorExit:
return
except MyException:
print("MyException!")
和Python不会计算在未来except
处理器。
使用Python 3.2或更早版本无法重现该错误,因此它看起来像散列随机化 (在Python 3.3中引入)随机化订单对象被清除; 这肯定解释了为什么你只在你的一些运行中看到错误,而不是在修复哈希顺序的早期Python运行中。
需要注意的是相互作用.__del__()
挂钩,并与其他的Python全局对象是记录与一个大红色的警告.__del__()
文档 :
警告 :由于调用
__del__()
方法的不稳定情况,将忽略执行期间发生的异常,并向sys.stderr
警告。 此外,当响应于被删除的模块而调用__del__()
时(例如,当完成程序的执行时),__del__()
方法引用的其他全局变量可能已被删除或正在被拆除(例如进口机械关闭)。 因此,__del__()
方法应该做到维持外部不变量所需的绝对最小值。 从版本1.5开始,Python保证在删除其他全局变量之前,从其模块中删除名称以单个下划线开头的全局变量; 如果不存在对这样的全局变量的其他引用,这可能有助于确保在__del__()
方法时导入的模块仍然可用。
我在Windows上的Python 3.3中遇到了同样的错误,区别在于我在自己的文件中定义了异常。 这些是我的代码文件:
$ cat FooError.py
class FooError(Exception):
pass
$ cat application.py
import FooError
try:
raise FooError('Foo not bar!')
Except FooError as e:
print(e)
这是我得到的例外:
TypeError:不允许捕获不从BaseException继承的类。
将import FooError
更改为from FooError import *
解决了该问题。 为了清楚起见,这是最终的代码:
$ cat FooError.py
class FooError(Exception):
pass
$ cat application.py
from FooError import *
try:
raise FooError('Foo not bar!')
Except FooError as e:
print(e)
我有同样的问题 - 但我错过了对异常类的导入。 所以解释器没有解析except子句中的类。
所以只需添加导入,希望一切都能正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.