Splunk SOAR中inspect.getsource返回错误函数源码问题求助
问题:inspect.getsource() 返回错误函数的源码(Splunk SOAR环境)
环境背景
运行在Splunk SOAR中,环境通过包装程序获取、解码并执行脚本,直接调用inspect无法正常获取源码,必须手动将文件导入自身。
问题现象
尝试获取get_id函数的源码时,eval("source.get_id")已正确指向目标函数对象,但inspect.getsource()却返回了前一个函数update_creds的源码,导致无法提取get_id中自动生成的phantom.act调用代码。
排查结论
问题源于inspect.getsource()依赖函数的__code__.co_firstlineno属性获取行号,但Splunk SOAR的包装程序导致该属性与实际文件中的行号不匹配,出现固定偏移,从而指向了前一个函数的定义位置。
解决办法
办法1:直接读取文件内容定位函数
绕过inspect的行号依赖,直接读取文件并通过函数定义行定位目标函数的源码:
def get_function_source(**kwargs): import re import sys import os sys.path.insert(0, '/scm/git/') # 处理文件名,去掉尖括号 filename = re.sub(r'(<|>)','',__file__) file_path = os.path.join('/scm/git/', f"{filename}.py") # 读取文件所有行 with open(file_path, 'r') as f: lines = f.readlines() target_func = kwargs["function"] func_start = None indent_level = None func_content = [] # 遍历找到函数定义起始行 for idx, line in enumerate(lines): stripped_line = line.strip() if stripped_line.startswith(f'def {target_func}('): func_start = idx # 记录函数定义的缩进级别 indent_level = len(line) - len(stripped_line) func_content.append(line) break if func_start is not None: # 收集函数内容直到遇到同级别缩进的新函数定义 for line in lines[func_start+1:]: stripped_line = line.strip() current_indent = len(line) - len(stripped_line) # 遇到同级别def就停止 if stripped_line.startswith('def ') and current_indent == indent_level: break func_content.append(line) function_source = ''.join(func_content) # 提取最后一行phantom.act调用 generated_code = re.findall(r'phantom.act\((.*)\)', function_source)[-1] return generated_code.replace("old_parameter", "new_parameter")
办法2:修正函数的行号属性
临时修改函数的co_firstlineno为实际文件中的行号,让inspect.getsource()能正确定位:
def get_function_source(**kwargs): import inspect import re import sys import os sys.path.insert(0, '/scm/git/') filename = re.sub(r'(<|>)','',__file__) source = __import__(filename) func = eval(f"source.{kwargs['function']}") file_path = os.path.join('/scm/git/', f"{filename}.py") # 找到函数在文件中的实际起始行号(inspect用1-based行号) with open(file_path, 'r') as f: lines = f.readlines() correct_firstlineno = None for idx, line in enumerate(lines, 1): if line.strip().startswith(f'def {kwargs["function"]}('): correct_firstlineno = idx break if correct_firstlineno: # 替换函数的co_firstlineno属性 func.__code__ = func.__code__.replace(co_firstlineno=correct_firstlineno) function_source = inspect.getsource(func) generated_code = re.findall(r'phantom.act\((.*)\)', function_source)[-1] return generated_code.replace("old_parameter", "new_parameter")
内容的提问来源于stack exchange,提问作者user23530071
相关产品推荐
相关产品推荐

