Python 3.12 Special Attribute - 26 - __builtins__

张开发
2026/4/20 5:47:41 15 分钟阅读

分享文章

Python 3.12 Special Attribute - 26 - __builtins__
Python 3.12 Special Attribute -__builtins____builtins__是 Python 中一个特殊的内置属性它存在于每个模块的全局命名空间中通常作为模块的属性。它提供了对 Python内置命名空间builtins的访问包含了所有内置函数如print、len、内置异常如Exception、内置常量如True、False等。理解__builtins__有助于深入掌握 Python 的作用域机制、动态修改内置行为尽管不推荐以及实现自定义执行环境。1.__builtins__的基本概念定义__builtins__是一个模块通常或字典它引用 Python 的内置命名空间。通过它可以访问所有内置名称。类型在大多数情况下例如在主模块中__builtins__是一个模块对象builtins模块在某些上下文如exec或eval的受限环境中它可能是一个字典。位置每个模块包括__main__的全局命名空间中都有__builtins__属性。它通常由解释器在模块初始化时自动设置。可写性__builtins__是可写的但直接修改它可能导致不可预知的行为例如破坏内置函数的可用性。通常不应修改。示例importbuiltinsprint(__builtins__isbuiltins)# True在大多数情况下print(__builtins__.printisprint)# True2.__builtins__与builtins模块的关系Python 标准库中有一个名为builtins的模块它直接暴露所有内置名称。__builtins__通常就是这个模块的引用。但需要注意在某些执行环境如exec或eval中指定了自定义的全局命名空间中__builtins__可能被设置为一个字典即{print: print, ...}而不是完整的builtins模块。验证importbuiltinsprint(__builtins__isbuiltins)# 输出 True在普通 Python 脚本中3. 不同模块中的__builtins__行为主模块__main____builtins__指向builtins模块。被导入的模块解释器在导入模块时会自动为该模块的全局命名空间设置__builtins__属性同样指向builtins模块除非被覆盖。exec或eval的受限环境如果调用exec(code, globals)时没有提供内置字典Python 会自动将__builtins__设置为当前内置模块的字典或模块。但如果提供了自定义globals且未包含__builtins__Python 会自动注入一个字典形式的__builtins__。4. 用途与典型场景动态访问内置函数通过__builtins__可以在运行时获取内置函数的引用例如getattr(__builtins__, len)。限制或替换内置函数在沙盒环境中可以通过替换__builtins__中的条目来禁用危险函数如open、eval但这种方法不是绝对安全的因为存在多种绕过方式。自省列出所有内置名称例如dir(__builtins__)。实现自定义执行环境在exec或eval中通过提供自定义的__builtins__字典来控制可用函数。5. 示例与逐行解析示例 1查看__builtins__的内容# 打印所有内置名称print(dir(__builtins__))# 获取特定内置函数print(__builtins__.len([1,2,3]))# 3逐行解析行代码解释2dir(__builtins__)列出__builtins__中所有名称包括len、print、Exception等。5__builtins__.len([1,2,3])通过__builtins__调用内置函数len。为什么这样写演示了__builtins__提供了访问所有内置名称的途径。示例 2检查__builtins__的类型print(type(__builtins__))# class module (在普通脚本中)print(__builtins__is__builtins__.__dict__)# False因为 __builtins__ 是模块不是字典注意在exec环境中__builtins__可能是一个字典。可以通过isinstance(__builtins__, dict)判断。示例 3动态调用内置函数通过名称字符串func_namemaxifhasattr(__builtins__,func_name):funcgetattr(__builtins__,func_name)print(func([1,5,3]))# 5逐行解析行代码解释1func_name max内置函数名的字符串。2hasattr(__builtins__, func_name)检查__builtins__是否有该名称。3func getattr(__builtins__, func_name)获取函数对象。4func([1,5,3])调用内置函数max。为什么这样写这种方式允许在运行时根据字符串动态调用内置函数适用于配置驱动或元编程。示例 4临时替换内置函数危险操作仅作演示original_print__builtins__.printdefmy_print(*args,**kwargs):original_print(Custom print:,*args)# ✅ 使用保存的原始函数__builtins__.printmy_printprint(Hello)# 输出: Custom print: Hello# 恢复__builtins__.printoriginal_printprint(Hello)# 输出: Hello逐行解析行代码解释1保存原始print函数以便后续恢复。3-5定义自定义print添加前缀。7替换__builtins__.print所有后续print调用都会使用新函数。9调用print输出自定义内容。11-12恢复原始print还原内置行为。为什么这样写演示了如何修改内置行为但强烈不建议在生产环境中使用因为这会影响整个进程且可能导致难以调试的 bug。通常只在测试或特殊框架中临时使用。示例 5在exec中使用自定义__builtins__custom_builtins{print:lambdax:print(fCustom:{x}),len:len,}code print(Hello) print(len([1,2,3])) exec(code,{__builtins__:custom_builtins})输出Custom: Hello 3逐行解析行代码解释1-4定义自定义内置字典只提供print和len其中print被修改。6-9待执行的代码使用了print和len。11exec执行将自定义的__builtins__作为全局字典的一部分传入。为什么这样写创建受限的执行环境只允许使用特定的内置函数。常用于代码沙盒或模板引擎中。6. 底层实现机制CPython在 CPython 中__builtins__的设置发生在模块初始化和执行代码块时。主模块__main__当 Python 启动时会创建一个主模块对象并将其全局字典中的__builtins__设置为builtins模块即PyEval_GetBuiltins()返回的模块。导入的模块在import语句加载模块时importlib会创建新的模块对象并自动将其__builtins__属性设置为builtins模块。这发生在_bootstrap._load_unlocked中。exec和eval当执行动态代码时Python 会根据提供的全局字典决定__builtins__的值如果全局字典中已有__builtins__键则使用其值。否则如果全局字典中包含了__builtins__且值为None则内置名称将不可用。否则Python 会自动注入一个__builtins__条目如果全局字典的__name__为__main__则设置为builtins模块否则设置为builtins.__dict__字典形式。内置模块 vs 字典在模块顶层__builtins__通常是一个模块对象因为直接使用模块可以保持完整的命名空间且效率更高。在动态代码exec中使用字典更轻量且方便进行受限控制。安全性尽管可以通过替换__builtins__来限制内置函数但仍存在绕过方式例如通过().__class__.__bases__[0].__subclasses__()等技巧访问危险函数。因此依赖__builtins__的沙盒并不安全。7. 注意事项与陷阱不要随意修改__builtins__修改全局内置函数会影响整个 Python 进程可能导致其他模块产生意外行为。__builtins__可能不是模块在exec或某些特定上下文中它可能是一个字典。因此不要假设它有__dict__属性或可以直接导入。builtins模块是更好的选择如果需要显式访问内置名称推荐直接导入builtins模块因为它更明确、更可靠。importbuiltinsprint(builtins.printisprint)# True与__builtin__Python 2的区别在 Python 3 中__builtins__代替了 Python 2 的__builtin__模块。避免在库代码中依赖__builtins__因为库可能被导入到自定义环境中其中__builtins__可能被修改。8. 与其他特殊属性的关系属性关系__name__模块名。__builtins__是模块的属性独立于__name__。__dict__模块的命名空间字典。__builtins__是该字典中的一个键。__file__模块的文件路径与__builtins__无关。builtins标准库模块通常与__builtins__指向同一个对象。9. 总结特性说明角色提供对 Python 内置命名空间的访问类型通常是builtins模块对象也可能是字典位置每个模块的全局命名空间访问方式__builtins__.function_name或直接导入builtins可写性可写但强烈不建议修改底层由解释器在模块初始化时自动设置典型用途动态访问内置函数、受限执行环境、自省最佳实践直接使用import builtins不要依赖__builtins__进行安全控制掌握__builtins__有助于深入理解 Python 的作用域和内置命名空间的管理。虽然日常开发中很少直接操作它但在编写框架、调试或实现动态执行环境时它是一个有用的工具。希望本文能帮助你全面掌握这一特殊属性。如果在学习过程中遇到问题欢迎在评论区留言讨论!

更多文章