Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么需要显式删除sys.exc_info()回溯?_Python - Fatal编程技术网

Python 为什么需要显式删除sys.exc_info()回溯?

Python 为什么需要显式删除sys.exc_info()回溯?,python,Python,我在不同的代码库中看到过,只是读了PyMOTW(参见第一条注释) 解释说,如果将回溯分配给来自sys.exc_info()[2]的变量,将创建一个循环,但这是为什么 这个问题有多大?我应该在我的代码库中搜索exc\u info的所有用法,并确保回溯被删除吗?回溯包含对所有活动帧的引用,而这些活动帧又包含对这些不同帧中所有局部变量的引用——这些引用是回溯和帧对象工作的一大部分,所以这并不奇怪。因此,如果您将引用添加回回溯(或者在临时添加了它之后未能及时删除它),您将不可避免地形成一个大的引用循环—

我在不同的代码库中看到过,只是读了PyMOTW(参见第一条注释)

解释说,如果将回溯分配给来自
sys.exc_info()[2]
的变量,将创建一个循环,但这是为什么


这个问题有多大?我应该在我的代码库中搜索
exc\u info
的所有用法,并确保回溯被删除吗?

回溯包含对所有活动帧的引用,而这些活动帧又包含对这些不同帧中所有局部变量的引用——这些引用是回溯和帧对象工作的一大部分,所以这并不奇怪。因此,如果您将引用添加回回溯(或者在临时添加了它之后未能及时删除它),您将不可避免地形成一个大的引用循环——这会干扰垃圾收集(如果循环中的任何对象属于超越终结器方法的类,则可能会完全停止垃圾收集)

特别是在一个长时间运行的程序中,干扰垃圾收集并不是最好的主意,因为您将保留并不真正需要的内存(超过必要的时间,或者无限期地保留,如果您通过让这些循环包含带有终结器的对象而基本上阻止了垃圾收集)

因此,最好尽快消除回溯,不管它们是否来自
exc_info

Python3(更新为原始答案):

在Python3中,问题中引用的建议已从Python文档中删除。我最初的答案(如下)仅适用于在文档中包含引用的Python版本

Python 2:

Python垃圾回收器最终会找到并删除循环引用,比如从堆栈框架内部引用回溯堆栈创建的循环引用,所以不要返回并重写代码。但是,今后,你可以听从

(其中记录了exc_info())并说明:

当您需要获取异常时

还有两个想法:

首先,为什么要运行
exc\u info()

如果你想捕捉一个异常,你不应该说:

try:
    ...
except Exception as e:  # or "Exception, e" in old Pythons
    ... do with with e ...
而不是在
sys
模块内乱搞对象

第二:好吧,我给了你很多建议,但还没有真正回答你的问题。:-)

为什么要创建一个循环?在简单的情况下,当一个对象引用自身时,就会创建一个循环:

a = [1,2,3]
a.append(a)
或者当两个对象相互引用时:

a = [1,2,3]
b = [4,5,a]
a.append(b)
在这两种情况下,当函数结束时,变量值仍然存在,因为它们被锁定在引用计数范围内:在另一个值先消失之前,两个值都不能消失!只有现代的Python垃圾回收器才能解决这个问题,方法是最终注意到循环并打破它

因此,理解这种情况的关键是,“回溯”对象——由
exc_info()
返回的第三个对象(在索引#2处)——包含调用异常时处于活动状态的每个函数的“堆栈帧”。这些堆栈帧不是“死”对象,显示调用execption时的真实情况;框架还活着!捕获异常的函数仍然是活动的,因此它的堆栈框架是一个有生命的东西,当它的代码执行以处理异常时(以及在完成“except”子句并开始工作时执行其他任何操作),它的变量引用仍在增长和丢失

因此,当您说
t=sys.exc_info()[2]
时,回溯中的一个堆栈帧-实际上,该帧属于当前正在运行的函数-现在其中有一个名为
t
的变量,该变量指向堆栈帧本身,创建一个循环,就像我上面展示的那样。

您提到的使用
[:2]
的建议从Python 3.3开始从文档中删除。原因解释如下。
[:2]
技巧不再有效,已处理异常的
\uuuuu回溯\uuuu
属性应改为
None
。相关政治公众人物:。
a = [1,2,3]
b = [4,5,a]
a.append(b)