Re: __builtins__ magic behavior



En Sun, 07 Sep 2008 14:00:48 -0300, Patrick Maupin <pmaupin@xxxxxxxxx> escribió:

__builtins__ in 2.5.2 doesn't seem to behave like I remember it did
the last time I did some custom stuff with it, a very long time ago.

This isn't surprising, because of ongoing optimization, but it's hard
to google for '__builtins__' so I didn't really find any documentation
on the current CPython behavior, which in some cases seems quite
strange to me.

The documentation node at http://docs.python.org/ref/naming.html has a
"here be dragons" note on __builtins__, which is nice as far as it
goes, but doesn't provide any help for people wanting to abuse the
current CPython implementation. Additionally, the sentence
immediately above the note, "__builtins__ can be set to a user-created
dictionary to create a weak form of restricted execution" not only
contradicts the note, but in some cases appears not to be true.

When the code below is run, either standalone or by importing it, the
builtins used are different depending on whether exec is used with
globals() or with a copy of globals(). Any explanations for this
behavior would be much appreciated.

Python takes some shortcuts when dealing with builtins. I'll just describe what happens (I won't say whether it is "right" or "wrong").
The exec statement, when given a string source, compiles it and eventually calls PyEval_EvalCodeEx, which creates a new frame using PyFrame_New and finally executes it.
A frame object contains a pointer to the previous frame, the code to be executed, a pointer to the current globals *and* a separate pointer to the current builtins.
Inside PyFrame_New, there is a shortcut: if the new frame and the previous one share the same globals, then the previous builtins are copied into the new frame. Only if the globals differ the builtins are searched in globals. From frameobject.c: /* If we share the globals, we share the builtins. Save a lookup and a call. */
It is this assumption that fails in your code.

If you want to execute some code with modified builtins, do not change __builtins__ in the *calling* code, but in the globals that you pass to the exec call. That appears to be the most logical approach, and the way the developers appear to have expected.

--
Gabriel Genellina

.



Relevant Pages

  • Re: share data inside s-function
    ... If all instances of your S-Function need to use the same link to this ... other program then you need to make the pointer a global. ... using globals doesn't affect the speed of execution in any way ...
    (comp.soft-sys.matlab)
  • Re: Bizarre additional calling overhead.
    ... test_func2.func_globals was an empty dict. ... test_func2 with globals set to globalsit ran just as fast as ... The built-in namespace associated with the execution of a code block is ... Even if the restricted mode implementation is now considered unsafe ...
    (comp.lang.python)
  • Re: Resources about program design in C
    ... that returns a pointer to the environment struct. ... are valid solutions if the requirement is not to have global variables. ... of globals in main and declare it in an include file, ...
    (comp.lang.c)
  • Re: 5.1, Data Corruption, Intel, Oh my! [patch] - Fatal trap 12
    ... > instruction at the return address in that frame. ... > with the frame pointer here and didn't get any useful information with ... I also have to assume that the function pointer is ... > stack pointer. ...
    (freebsd-current)
  • Re: pointer address is physical or virtual.
    ... begins its execution and exits its execution.) ... void afun ... Pointer: 0x804844e ... physicall one. ...
    (comp.os.linux.development.system)