
本文介绍一种基于 sys.modules 的可靠方法,用于在运行时区分模块中的全局变量是本模块定义的还是从其他模块导入的,并准确获取其原始定义模块名,适用于依赖层级校验等场景。
本文介绍一种基于 `sys.modules` 的可靠方法,用于在运行时区分模块中的全局变量是本模块定义的还是从其他模块导入的,并准确获取其原始定义模块名,适用于依赖层级校验等场景。
在 Python 项目中,尤其是分层架构(如 core / service / api)中,常需确保低层模块不反向依赖高层模块。为此,一个关键前提是:能准确识别某模块(如 b.py)中使用的符号(如 CONSTANT)是否来自外部导入,以及它最初定义在哪个模块中。
直接使用 b.__dict__ 或 inspect.getmembers(b) 只能列出所有全局名称及其值,但无法区分 CONSTANT(来自 a)和 CONSTANT2(本地定义)。而 inspect.getmodule(obj) 对基本类型(如 int、list)无效——因为整数 2 本身不携带模块归属信息。
核心思路:Python 导入机制会将所有已加载模块缓存在 sys.modules 中;每个模块的 __dict__(即 vars(module))记录了其导出的所有名称与对象。我们可以逆向构建一张「全局名 → 定义模块」的映射表,再结合当前模块的 globals() 进行交叉匹配。
以下是一个完整、可复用的检测逻辑(建议封装为工具函数):
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
立即学习“Python免费学习笔记(深入)”;
import sys
from types import ModuleType
def get_imported_symbols(module):
"""
返回当前模块中所有从外部导入的符号及其源模块名。
排除双下划线特殊属性、模块类型对象及内置/动态生成对象。
"""
# 构建 {symbol_name: defining_module} 映射(仅含非 dunder 名)
name_to_module = {}
for mod in sys.modules.values():
if mod is None:
continue
for name, obj in vars(mod).items():
if not (name.startswith('__') and name.endswith('__')):
# 避免覆盖:优先保留首次出现的定义(符合 Python 导入顺序语义)
if name not in name_to_module:
name_to_module[name] = mod
# 筛选当前模块 globals() 中存在于映射内、且非模块类型的项
result = []
for name, obj in module.__dict__.items():
if name in name_to_module and not isinstance(obj, ModuleType):
defining_mod = name_to_module[name]
# 确保不是 self-reference:排除定义在本模块自身的符号
if defining_mod is not module:
result.append((name, defining_mod.__name__))
return result
# 示例用法(在 b.py 中):
# from a import CONSTANT
# CONSTANT2 = 4
# print(get_imported_symbols(sys.modules[__name__]))
# 输出:[('CONSTANT', 'a')]注意事项:
- 该方法依赖 sys.modules 的完整性,因此需在所有相关模块均已成功导入后调用;
- 不适用于 from module import * 引入的符号(因未显式绑定名称,且可能被重写),推荐显式导入;
- 若多个模块定义同名符号(如两个 utils.py 都有 helper),此方法返回首个加载模块中的定义,符合 Python 导入解析规则;
- 为保障准确性,建议在模块初始化末尾或独立检查脚本中执行,避免动态修改 globals() 干扰判断。
通过该机制,你可系统性扫描项目各模块,自动报告违规反向导入(如 core 模块中出现 from api import xxx),从而强化架构约束,提升代码可维护性与演进安全性。

















