I actually want to create a new local. I know it sounds dubious, but I think I have a nice use case for this. Essentially my problem is that this code throws "NameError: global name 'eggs' is not defined" when I try to print eggs:
def f():
import inspect
frame_who_called = inspect.stack()[1][0]
frame_who_called.f_locals['eggs'] = 123
def g():
f()
print(eggs)
g()
I found this old thing:
http://mail.python.org/pipermail/python-dev/2005-January/051018.html
Which would mean I might be able to do it using ctypes and calling some secret function, though they only talked about updating a value. But maybe there's an easier way?
As Greg Hewgill mentioned in a comment on the question, I answered another question about modifying locals
in Python 3, and I'll give a bit of a recap here.
There is a post on the Python 3 bug list about this issue -- it's somewhat poorly documented in the Python 3 manuals. Python 3 uses an array for locals instead of a dictionary like in Python 2 -- the advantage is a faster lookup time for local variables (Lua does this too). Basically, the array is defined at "bytecode-compile-time" and cannot be modified at runtime.
See specifically the last paragraph in Georg Brandl's post on the bug list for finer details about why this cannot (and probably never will) work in Python 3.
I am highly curious as to your use case. Why on Earth are you trying to poke a new local into the caller's frame, rather than simply doing something like this:
def f():
return 123
def g():
eggs = f()
print(eggs)
After all, you can return a tuple with as many values as you like:
def f():
return 123, 456, 789
def g():
eggs, ham, bacon = f()
print(eggs, ham, bacon)
In Python 2.*, you can get such code to work by defeating the normal optimization of locals:
>>> def g():
... exec 'pass'
... f()
... print(eggs)
The presence of an exec
statement causes Python 2 to compile g
in a totally non-optimized fashion, so locals are in a dict instead of in an array as they normally would be. (The performance hit can be considerable).
This "de-optimization" does not exist in Python 3, where exec
is not a statement any more (not even a keyword, just a function) -- even putting parentheses after it doesn't help...:
>>> def x():
... exec('a=23')
... print(a)
...
>>> x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in x
NameError: global name 'a' is not defined
>>>
i.e., not even exec
can now "create locals" that were not know at def
-time (i.e., when the compiler did its pass to turn the function body into bytecode).
Your best bet would be to give up. Second best would be to have your f
function inject new names into the caller's globals
-- those are still a dict, after all.