__builtins__ はモジュール? 辞書?

__builtins__ って必ずモジュールだと思ってたけど、そうでもないらしい。

foo.py:

import sys
print "(foo.py): __builtins__: ", type(__builtins__)
print "(foo.py): sys         : ", type(sys)

bar.py:

import foo
import sys
print "(bar.py): __builtins__: ", type(__builtins__)
print "(bar.py): sys         : ", type(sys)

実行結果:

$ python -V
Python 2.5.4
$ python foo.py
(foo.py): __builtins__:  <type 'module'>
(foo.py): sys         :  <type 'module'>
$ python bar.py
(foo.py): __builtins__:  <type 'dict'>     # 辞書になってる!
(foo.py): sys         :  <type 'module'>
(bar.py): __builtins__:  <type 'module'>
(bar.py): sys         :  <type 'module'>

__builtins__ は、foo.py を直接実行したときはモジュールだけど、import されたときは辞書らしい。
マジですか。

どちらのときでも同じように操作するには、モジュールを辞書に変換してやればいいみたい。

foo.py:

if isinstance(__builtins__, dict):
    _d = __builtins__             # 辞書ならそのまま
else:
    _d = __builtins__.__dict__    # モジュールなら辞書へ

_d['Str']     = str
_d['List']    = list
_d['Dict']    = dict

print "(foo.py): __builtins__: ", type(__builtins__)
print "(foo.py): Str, List, Dict: ", Str, List, Dict

bar.py:

import foo
print "(foo.py): __builtins__: ", type(__builtins__)
print "(foo.py): Str, List, Dict: ", Str, List, Dict

実行結果:

$ python foo.py
(foo.py): __builtins__:  <type 'module'>
(foo.py): Str, List, Dict:  <type 'str'> <type 'list'> <type 'dict'>
$ python bar.py
(foo.py): __builtins__:  <type 'dict'>
(foo.py): Str, List, Dict:  <type 'str'> <type 'list'> <type 'dict'>
(foo.py): __builtins__:  <type 'module'>
(foo.py): Str, List, Dict:  <type 'str'> <type 'list'> <type 'dict'>