繁体   English   中英

有时显示异常TypeError警告,有时不使用生成器的throw方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM