Python 3.8/3.10中inspect.getsource获取类源码差异及兼容方案咨询
Python 3.8与3.10中inspect.getsource获取类源码的差异及兼容方案
差异原因
- Python 3.8及更早版本的
inspect.getsource()在处理被装饰类时,只会提取类定义本身的源码,不会包含上方的装饰器。这是因为当时模块的实现逻辑是直接定位到类的定义节点,跳过了装饰器语法所在的代码段。 - Python 3.10对
inspect模块的源码定位逻辑做了优化,能够识别并包含类定义上方的装饰器代码,因此调用inspect.getsource(Test)会返回带@dec的完整源码。
兼容Python 3.8的解决方案
要在Python 3.8中获取包含装饰器的类源码,可以手动向上遍历源码文件,收集类定义上方的装饰器行,再和类源码拼接。具体实现如下:
import inspect def dec(clz): return clz @dec class Test: pass def get_source_with_decorators(obj): # 获取类的源码行和起始行号(行号从1开始计数) class_lines, start_line = inspect.getsourcelines(obj) source_file = inspect.getsourcefile(obj) # 读取整个源码文件的内容 with open(source_file, 'r', encoding='utf-8') as f: all_lines = f.readlines() # 从类定义的上一行开始向上查找装饰器 decorator_lines = [] current_idx = start_line - 2 # 转换为0索引的行号,start_line是类定义行,减2得到上一行的索引 while current_idx >= 0: line_content = all_lines[current_idx].strip() if line_content.startswith('@'): decorator_lines.insert(0, all_lines[current_idx]) current_idx -= 1 else: # 遇到非装饰器行,停止遍历 break # 拼接装饰器和类的源码 return ''.join(decorator_lines + class_lines) # 测试调用 print(get_source_with_decorators(Test))
这个方法的核心是通过inspect.getsourcelines()拿到类的起始位置,再从该位置向上遍历源码文件,收集所有连续的装饰器行,最后和类本身的源码拼接,就能得到包含装饰器的完整代码。
内容的提问来源于stack exchange,提问作者cinqS
相关产品推荐
相关产品推荐

