Skip to content Skip to sidebar Skip to footer

Why Does Modifying Parent Frame In Python Work Only For Module Frames?

I was playing around with inspect.stack(). I tried modifying a local variable of the parent frame, and it seems to work only if the parent frame is module-level. The following code

Solution 1:

The f_locals of a module stack frame are its globals()! You can verify this by printing the is comparison with globals() inside the modify function:

def modify():
    print(inspect.stack()[1][0].f_locals isglobals())
    inspect.stack()[1][0].f_locals['a'] = 8888

With this change the output is:

$python3 modify.py 
10False1020True8888

Modifying the dictionary returned by globals()does work (see this question). It is explicitlydocumented that modules implement their namespace with a simple dict:

Modules are imported by the import statement (see section The import statement). A module object has a namespace implemented by a dictionary object (this is the dictionary referenced by the func_globals attribute of functions defined in the module).

However the dictionary returned by locals() does not have to be the local namespace:

Note The contents of this dictionary should not be modified; changes may not affect the values of local and free variables used by the interpreter.

In some versions of python2 modifying locals() works when using the exec statement inside the function. Try to add exec '' inside the outer function and see whether the output changes (it isn't guaranteed to change! However it is more likely).

Edit: On python 2.7.6 I can make it work if the stack frame uses the exec statement and there is no assignment to a local variable in the code. For example with outer defined as:

def outer():
    exec('a = 10')
    print(a)
    modify()
    print(a)
    locals()['a'] = 9999print(a)

I get the output:

$python2modify.py10False8888999920True8888

But if I add a = 10 after the exec as in:

def outer():
    exec('a = 10')
    a = 10print(a)
    modify()
    print(a)
    locals()['a'] = 9999print(a)

The result is:

$python2 modify.py 
10False101020True8888

I hope this shows you that the conditions in which assigning to locals work are really few and absolutely not reliable.

AFAIK in python3 the dictionary returned by locals() is always just a copy of the real namespace, so modifying it never works. However there is no guarantee either.

The value returned by the f_locals attribute is simply the value returned by locals() at that point.

In summary: no, there is no reliable way to modify the local namespace of a generic stack frame. You cannot modify, delete nor add new local variables to a generic stack frame's namespace.

Post a Comment for "Why Does Modifying Parent Frame In Python Work Only For Module Frames?"