Python function local variable scope during exceptions

Reference Information. I am doing COM programming TestStand National Instruments in Python. TestStand complains that if the objects were not “released” properly (the debugging dialog box “objects not released properly” appears in it). The way Python TestStand COM objects are released in Python is to ensure that all variables no longer contain the object, for example. del()or set them to None. Or, while the variables are functional local variables, the object is freed as soon as the variable goes out of scope when the function completes.

Well, I followed this rule in my program, and my program frees the object properly, until there are exceptions. But if I get an exception, I get a "objects not released" message from TestStand. This seems to indicate that local function variables usually do not go out of scope when an exception occurs.

Here is an example of simplified code:

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

When this is executed, as shown, it shows what I expect:

Init outer_object
Init inner_object
Del inner_object
Del outer_object

But if I uncomment the line raise Exception..., instead I get:

Init outer_object
Init inner_object
Del outer_object
Traceback (most recent call last):
...
Exception: Test exception
Del inner_object

inner_object deleted due to exception.

If I uncomment the lines that set both parameter, and local_variablein None, I get what I expect:

Init outer_object
Init inner_object
Del inner_object
Del outer_object
Traceback (most recent call last):
...
Exception: Test exception

, Python , ? -, , ? " " ?

+3
3

, , , . docs :

, return [[NB: " " inspect, !]], , . , , , Pythons . , , , . , ( ) finally. , , Python gc.disable(). :

def handle_stackframe_without_leak():
    frame = inspect.currentframe()
    try:
        # do something with the frame
    finally:
        del frame
+2

. finally.

+1

According to this answer for another question, you can check local variables per frame in the exception trace through tb_frame.f_locals. Thus, it seems that objects are kept alive throughout the exception handling.

0
source

Source: https://habr.com/ru/post/1728270/


All Articles