problem with exec and locals()

  • Thread starter rocksportrocker
  • Start date
R

rocksportrocker

Hi,

the following code does not work until I ommit the "a=0" statement.


def test():
exec "a=3" in locals()
print a
a=0

test()

print raises:
UnboundLocalError: local variable 'a' referenced before
assignment

Can anybody explain what is going wrong here ?

Greetings, Uwe
 
M

Mel

rocksportrocker said:
Hi,

the following code does not work until I ommit the "a=0" statement.


def test():
exec "a=3" in locals()
print a
a=0

test()

print raises:
UnboundLocalError: local variable 'a' referenced before
assignment

Can anybody explain what is going wrong here ?

AFAIK, local variables are implemented rather like __slots__ in new-style
classes. This is a very valuable efficiency measure, but it can cause this
kind of trouble. Without `a=0`, the bytecode compiler makes no slot for a,
and dis.dis shows the following bytecode for test: 2 0 LOAD_CONST 1 ('a=3')
3 LOAD_NAME 0 (locals)
6 CALL_FUNCTION 0
9 DUP_TOP
10 EXEC_STMT

3 11 LOAD_NAME 1 (a)
14 PRINT_ITEM
15 PRINT_NEWLINE
16 LOAD_CONST 0 (None)
19 RETURN_VALUE

At address 11, LOAD_NAME 1(a) gets the value that was set by exec.

With a=0, the code is 2 0 LOAD_CONST 1 ('a=4')
3 LOAD_NAME 0 (locals)
6 CALL_FUNCTION 0
9 DUP_TOP
10 EXEC_STMT

3 11 LOAD_FAST 0 (a)
14 PRINT_ITEM
15 PRINT_NEWLINE

4 16 LOAD_CONST 2 (0)
19 STORE_FAST 0 (a)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE

and here, the value of a is found in slot 0 via LOAD_FAST. Slot 0 is used
because a=0 forced a to be a local variable.

Apparently, exec in locals() knows nothing about slots (because locals() is
the only dictionary in the universe where slots would be involved ? --
perhaps not, but close).

Mel.
 
U

Uwe Schmitt

rocksportrockerwrote:







AFAIK, local variables are implemented rather like __slots__ in new-style
classes.  This is a very valuable efficiency measure, but it can cause this
kind of trouble.  Without `a=0`, the bytecode compiler makes no slot for a,
and dis.dis shows the following bytecode for test:>>> dis.dis (test)

  2           0 LOAD_CONST               1 ('a=3')
              3 LOAD_NAME                0 (locals)
              6 CALL_FUNCTION            0
              9 DUP_TOP
             10 EXEC_STMT

  3          11 LOAD_NAME                1 (a)
             14 PRINT_ITEM
             15 PRINT_NEWLINE
             16 LOAD_CONST               0 (None)
             19 RETURN_VALUE

At address 11, LOAD_NAME 1(a) gets the value that was set by exec.

With a=0, the code is>>> dis.dis(test2)

  2           0 LOAD_CONST               1 ('a=4')
              3 LOAD_NAME                0 (locals)
              6 CALL_FUNCTION            0
              9 DUP_TOP
             10 EXEC_STMT

  3          11 LOAD_FAST                0 (a)
             14 PRINT_ITEM
             15 PRINT_NEWLINE

  4          16 LOAD_CONST               2 (0)
             19 STORE_FAST               0 (a)
             22 LOAD_CONST               0 (None)
             25 RETURN_VALUE

and here, the value of a is found in slot 0 via LOAD_FAST.  Slot 0 is used
because a=0 forced a to be a local variable.

Apparently, exec in locals() knows nothing about slots (because locals() is
the only dictionary in the universe where slots would be involved ? --
perhaps not, but close).

        Mel.

Thanks for your answer. I wonder if this is a bug, or did I miss
something
in the docs ???

Greetings, Uwe
 
P

Peter Otten

Uwe said:
Thanks for your answer. I wonder if this is a bug, or did I miss
something in the docs ???

Hm, the documentation has an explicit warning:

http://docs.python.org/lib/built-in-funcs.html#l2h-47

"""
locals( )
Update and return a dictionary representing the current local symbol table.
Warning: The contents of this dictionary should not be modified; changes
may not affect the values of local variables used by the interpreter.
"""

By the way, the local namespace is affected if you don't provide it
explicitly:
.... exec "a=42"
.... print a
.... a = "whatever"
....42

Peter
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top