If this is really only about globals and builtins, then you can just initialize each module's dictionary with a copy of builtins. (Or cache them in the module __dict__ on the first lookup, since you know where it would have gone.)
Phillip J. Eby:
Interesting thought. The same process that currently loads the __builtins__ member could instead update the namespace directly.
There's only one problem with this idea, and it's a big one: 'import *' would now include all the builtins, causing one module's builtins (or changes thereto) to propagate to other modules.
Why is this bad?
The reason to import * is that you intend to use the module's members as if they were your own. If the other module actually has modified a builtin, you'll need to do the same, or the imported members won't work quite right.
If you're sure you don't want everything the other module changed, then you shouldn't be using *.
If you absolutely have to use * but not get builtins changed, then you can reupdate from builtins after the import.
... declare that the any builtin used in a module that's known to be a builtin, is allowed to be optimized to the meaning of that builtin.
In effect, '__builtins__' should be considered an implementation detail, not part of the language,
Many builtins (None, True, KeyError) are effectively keywords, and I would agree.
Others, like __debug__, are really used for intermodule communication, because there isn't any other truly global namespace. (Perhaps there should be a conventional place to look, such as a settings module?)