Exec Statement Question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • =?ISO-8859-1?Q?Gregory_Pi=F1ero?=

    #1

    Exec Statement Question

    I'm curious why this code isn't working how I expect it to:

    import sys
    d=3

    def func1(a,b,c):
    print a,b,c,d
    print sys.path

    exec "func1(1,2, 3)" in {'func1':func1}

    ----
    returns:
    1 2 3 3
    [ sys.path stuff ....]

    Since I'm telling exec to operate only within the context of the
    dictionary I give it, why does it still see sys.path and d? I figured
    it would throw a NameError.

    Is there a way to call exec such that it won't have access to any more
    objects than I explicitly give it?

    Thanks,

    Greg
  • 7stud

    #2
    Re: Exec Statement Question

    On Apr 8, 11:31 pm, "Gregory Piñero" <gregpin...@gma il.comwrote:
    I'm curious why this code isn't working how I expect it to:
    >
    import sys
    d=3
    >
    def func1(a,b,c):
    print a,b,c,d
    print sys.path
    >
    exec "func1(1,2, 3)" in {'func1':func1}
    >
    ----
    returns:
    1 2 3 3
    [ sys.path stuff ....]
    >
    Since I'm telling exec to operate only within the context of the
    dictionary I give it, why does it still see sys.path and d? I figured
    it would throw a NameError.
    >
    Is there a way to call exec such that it won't have access to any more
    objects than I explicitly give it?
    >
    Thanks,
    >
    Greg
    I think the way it works is that when the def is parsed, a function
    object is created and assigned to the name func1. When the function
    object is created, d is "bound" to the global value 3, while a,b,c lie
    in wait for arguments to land in their gullets like venus fly traps.
    Your dictionary has a key whose value is a reference to the function
    object, which already has the value 3 bound to d.


    Comment

    • Alex Martelli

      #3
      Re: Exec Statement Question

      Gregory Piñero <gregpinero@gma il.comwrote:
      I'm curious why this code isn't working how I expect it to:
      >
      import sys
      d=3
      >
      def func1(a,b,c):
      print a,b,c,d
      print sys.path
      >
      exec "func1(1,2, 3)" in {'func1':func1}
      >
      ----
      returns:
      1 2 3 3
      [ sys.path stuff ....]
      >
      Since I'm telling exec to operate only within the context of the
      dictionary I give it, why does it still see sys.path and d? I figured
      it would throw a NameError.
      >
      Is there a way to call exec such that it won't have access to any more
      objects than I explicitly give it?
      func1 accesses its globals through func1.func_glob als (which you can't
      reassign -- it's a read-only attribute).

      You may make a new function object w/ a different globals dict...:
      >>g = type(func1)(fun c1.func_code, {})
      and that will fail (even when called directly, but similarly if exec'd)
      as it's missing key 'd' in its globals:
      >>g(1, 2, 3)
      1 2 3
      Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 2, in func1
      NameError: global name 'd' is not defined


      The globals dict you pass to exec is the globals at the time of CALL,
      not the globals seen from INSIDE func1; that's always going to be the
      func_globals attribute of the function object, so you need to control
      that (by suitably building a new function object as you require).


      Alex

      Comment

      • Gabriel Genellina

        #4
        Re: Exec Statement Question

        7stud wrote:
        On Apr 8, 11:31 pm, "Gregory Piñero" <gregpin...@gma il.comwrote:
        Is there a way to call exec such that it won't have access to any more
        objects than I explicitly give it?
        >
        I think the way it works is that when the def is parsed, a function
        object is created and assigned to the name func1. When the function
        object is created, d is "bound" to the global value 3, while a,b,c lie
        in wait for arguments to land in their gullets like venus fly traps.
        Your dictionary has a key whose value is a reference to the function
        object, which already has the value 3 bound to d.
        Not exactly. As Georg Brandl said, the function has a reference to the
        *globals* currently in use when it was defined, not directly to the
        name "d".

        To the OP: If you want a function with almost "empty" globals, compile
        it the same way you used to execute it:
        >>text = """def func1(a):
        .... print a
        .... print b
        ....
        .... func1(3)
        .... print func1.func_glob als.keys()
        .... """
        >>>
        >>exec text in {}
        3
        Traceback (most recent call last):
        File "<stdin>", line 1, in ?
        File "<string>", line 5, in ?
        File "<string>", line 3, in func1
        NameError: global name 'b' is not defined
        >>exec text in {"b": 123}
        3
        123
        ['__builtins__', 'func1', 'b']
        >>>
        I said *almost* empty because Python may insert other keys into the
        globals, like __builtins__ above (see http://docs.python.org/ref/exec.html)

        --
        Gabriel Genellina

        Comment

        • gregpinero@gmail.com

          #5
          Re: Exec Statement Question

          Thanks for the responses everyone. That does make sense to me now.

          -Greg

          Comment

          Working...