Eryk Sun added the comment:

As shown above, exec and eval default to calling PyEval_GetBuiltins when the 
globals dict doesn't define '__builtins__'. PyEval_GetBuiltins uses the current 
frame's f_builtins. If there isn't a current frame, it defaults to the 
interpreter's builtins, which should be the dict of the builtins module. 

If exec and eval didn't do this, the default behavior would be to create a 
minimal f_builtins dict for the new frame. This dict only contains a reference 
to None, and it doesn't get set as '__builtins__' in globals. For example:

    from inspect import currentframe
    from ctypes import pythonapi, py_object
    g = py_object({'currentframe': currentframe})
    code = py_object(compile('currentframe()', '', 'eval'))
    frame = pythonapi.PyEval_EvalCode(code, g, g)

    >>> frame.f_builtins
    {'None': None}
    >>> frame.f_globals
    {'currentframe': <function currentframe at 0x7f2fa1d6c2f0>}

This minimalist default isn't useful in general. exec and eval are saving 
people from the tedium of having to manually define a useful __builtins__ when 
passing a new globals. The frame object uses this __builtins__ to initialize 
its f_builtins. Also, it knows to look for __builtins__ as a module, as used by 
__main__:

    g = py_object({'currentframe': currentframe, '__builtins__': __builtins__})
    frame = pythonapi.PyEval_EvalCode(code, g, g)

    >>> frame.f_builtins is vars(__builtins__)
    True

----------
nosy: +eryksun

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue26363>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to