背景:我正在用Python语言对National Instruments的TestStand进行COM编程。如果对象没有正确“释放”,TestStand会报错(它会弹出一个“对象没有正确释放”的调试对话框)。在Python语言中释放TestStand COM对象的方法是确保所有变量不再包含该对象-例如,对它们执行del()操作,或者将它们设置为None。或者,只要变量是函数局部变量,当函数结束时,一旦变量超出作用域,对象就会被释放。
嗯,我在我的程序中遵循了这个规则,只要没有异常,我的程序就会正确地释放对象。但是如果我得到一个异常,我就会收到来自TestStand的"objects not released“消息。这似乎表明,当发生异常时,函数局部变量通常不会超出作用域。
下面是一个简化的代码示例:
class TestObject(object):
def __init__(self, name):
self.name = name
print("Init " + self.name)
def __del__(self):
print("Del " + self.name)
def test_func(parameter):
local_variable = parameter
try:
pass
# raise Exception("Test exception")
finally:
pass
# local_variable = None
# parameter = None
outer_object = TestObject('outer_object')
try:
inner_object = TestObject('inner_object')
try:
test_func(inner_object)
finally:
inner_object = None
finally:
outer_object = None如图所示,它显示了我所期望的结果:
Init outer_object
Init inner_object
Del inner_object
Del outer_object但是如果我取消对raise Exception...行的注释,我会得到:
Init outer_object
Init inner_object
Del outer_object
Traceback (most recent call last):
...
Exception: Test exception
Del inner_object由于异常,inner_object被延迟删除。
如果我取消注释将parameter和local_variable都设置为None的行,那么我会得到我期望的结果:
Init outer_object
Init inner_object
Del inner_object
Del outer_object
Traceback (most recent call last):
...
Exception: Test exception那么,当Python中发生异常时,函数局部变量到底会发生什么呢?它们是否被保存在某个地方,这样它们就不会像往常一样超出范围了?控制这种行为的“正确方式”是什么?
发布于 2010-01-13 23:49:28
您的异常处理可能是通过保留对frames的引用来创建引用循环。正如the docs所说:
注意保持对frame对象的引用,如在frame的第一个元素中发现的记录这些函数返回[[NB:“ functions”这里指的是模块中的一些
inspect__,但本段的其余部分应用范围更广!]],会导致您的程序创建引用循环。一旦创建了引用周期,即使启用了Python的可选周期检测器,可以从形成周期的对象访问的所有对象的生命周期也会变得更长。如果必须创建这样的循环,重要的是要确保它们被显式打破,以避免延迟销毁对象和增加内存消耗。尽管周期检测器会捕捉到这些,但通过删除finally子句中的周期,可以确定帧(和局部变量)的销毁。如果在编译Python或使用gc.disable()时禁用了周期检测器,这一点也很重要。例如:
def handle_stackframe_without_leak():
frame = inspect.currentframe()
try:
# do something with the frame
finally:
del frame发布于 2010-01-13 17:32:05
函数的作用域是整个函数。在finally中处理此问题。
发布于 2013-02-06 09:27:58
根据this answer for another question的说法,可以通过tb_frame.f_locals进行inspect local variables on the frame in an exception traceback。因此,在异常处理期间,对象看起来确实是“活动的”。
https://stackoverflow.com/questions/2055611
复制相似问题