problem with exec and locals()

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rocksportrocker

    #1

    problem with exec and locals()


    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:
    UnboundLocalErr or: local variable 'a' referenced before
    assignment

    Can anybody explain what is going wrong here ?

    Greetings, Uwe
  • Mel

    #2
    Re: problem with exec and locals()

    rocksportrocker wrote:
    >
    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:
    UnboundLocalErr or: 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:
    >>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.

    Comment

    • Uwe Schmitt

      #3
      Re: problem with exec and locals()

      On 1 Jul., 15:15, Mel <mwil...@the-wire.comwrote:
      rocksportrocker wrote:
      >
      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:
           UnboundLocalErr or: 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:>>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(tes t2)
      >
        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

      Comment

      • Peter Otten

        #4
        Re: problem with exec and locals()

        Uwe Schmitt wrote:
        >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 ???
        Hm, the documentation has an explicit warning:



        """
        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:
        >>def f():
        .... exec "a=42"
        .... print a
        .... a = "whatever"
        ....
        >>f()
        42

        Peter

        Comment

        • Gabriel Genellina

          #5
          Re: problem with exec and locals()

          En Fri, 11 Jul 2008 03:51:39 -0300, Uwe Schmitt
          <rocksportrocke r@googlemail.co mescribi�:
          On 1 Jul., 15:15, Mel <mwil...@the-wire.comwrote:
          >rocksportrocke rwrote:
          >>
          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:
               UnboundLocalErr or: 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,
          >
          Thanks for your answer. I wonder if this is a bug, or did I miss
          something
          in the docs ???
          Read the warnings in the docs for the locals() builtin function:

          and the execfile function:


          --
          Gabriel Genellina

          Comment

          Working...