say, I have very simple piece of code
py = """
a = 1
print (f'before all {a=}')
def bar(n):
print(f'bye {n=}')
def foo(n):
print(f'hello {n=}')
bar(n)
bar ('just works')
foo ('sara')
"""
loc = {}
glo = {}
bytecode = compile(py, "script", "exec")
exec(bytecode, glo, loc)
as you can see I defined two functions: bar & foo and called both of them with results:
before all a=1
bye n='just works'
hello n='sara'
Traceback (most recent call last):
File "/home/bla-bla/pythonProject/main_deco2.py", line 43, in <module>
exec(bytecode, glo, loc)
File "script", line 13, in <module>
File "script", line 10, in foo
NameError: name 'bar' is not defined
and this leaves me puzzled, as I don't understand why function foo doesn't see bar when just a second ago I was able to call bar without a problem ?
From the docs:
If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition.
That's not what you want, so don't provide a locals.
glo = {}
exec(bytecode, glo)
Output, for reference:
before all a=1
bye n='just works'
hello n='sara'
bye n='sara'
An important diagnostic:
>>> dis.dis(bytecode)
2 0 LOAD_CONST 0 (1)
2 STORE_NAME 0 (a)
3 4 LOAD_NAME 1 (print)
6 LOAD_CONST 1 ('before all a=')
8 LOAD_NAME 0 (a)
10 FORMAT_VALUE 2 (repr)
12 BUILD_STRING 2
14 CALL_FUNCTION 1
16 POP_TOP
I omitted most of the result, but the first few lines show what is going on. Accesses to a and bar use the LOAD_NAME and STORE_NAME opcodes, which use the locals first. (It cannot use LOAD_FAST because it is not a compiled function.) To work around this, simply mark the necessary names as global explicitly.
Unfortunately, I don't have a good answer for why it does this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With