Python的inspect获取源代码返回不相关的源代码
我需要获取一个叫做 'get_id' 的函数的源代码,但使用 inspect.getsource() 时,它却返回了 'update_creds' 函数的源代码,我不知道为什么会这样。
关于环境的一些具体信息:它在 Splunk 的 SOAR 上运行,从堆栈跟踪来看,似乎是在运行一个包装程序来获取、解码和执行脚本,所以仅仅请求 inspect 找源代码似乎不太管用,除非我手动将文件导入到自身。
这是我正在调试的代码:
def update_creds(**kwargs):
print("update_creds")
# Function header I cannot touch
def get_id(**kwargs):
# inspect.stack()[0][3] gets the name of the function we are currently in
exec(get_new_return(function=inspect.stack()[0][3]))
return
# Automatically generated code I cannot touch
phantom.act("old_parameter","other_parameters_that_change")
return
# Function header I cannot touch
def get_function_source(**kwargs):
import inspect
import re
import sys
# We have to add the git repo to the system path so we can import the file
sys.path.insert(0, '/scm/git/')
# Get the file name from __file__ (its formatted within angle brackets, so we get rid of them
source=__import__(re.sub(r'(<|>)','',__file__))
# use eval to specifially refer to this files function object.
# using debug comments, the eval does indeed refer to the correct object I want the source from
# However, the return of inspect.getsource() gives me the source of another function
function_source=inspect.getsource(eval("source."+kwargs["function"]))
generated_code=re.findall(r'phantom.act\((.*)\)', function_source)[-1]
return generated_code.replace("old_parameter", "new_parameter")
get_id()
如果你真的想知道我为什么要这样做,这个环境使用代码块来生成 Python 代码,特别是函数定义和最终的函数调用来继续执行。然而,我需要在下一个函数调用中添加一个参数,所以我使用 inspect.getsource() 来获取最终的函数调用,添加参数,然后调用它,并提前返回。
我试着追踪它是在哪里失去对正确函数的引用的,似乎是在调用 inspect.getsource() 的时候。我期待的是 'get_id' 函数的源代码,而不是 'update_creds' 函数。
在研究 getsource 的工作原理时,我想这可能和函数的名字有关,但从我能看到的,名字之间没有任何共同点。我能想到的唯一其他情况是,如果 getsource 是根据行号来引用的,而它错误地使用了一个文件的行号来引用另一个文件,但我不知道怎么强制 inspect 确保它引用的是同一个文件。
编辑:为了提供更多上下文,我在代码块中添加了更多内容。在添加上下文时,我注意到 update_creds 是在 get_id 之上的函数,所以就好像 inspect.getsource() 需要再往下一个函数定义,但我不知道这是否是偶然的,或者它是否总是会偏差一个。如果它总是偏差一个,我该如何让 getsource 给我下一个函数呢?
1 个回答
在你的代码中,get_id()
这个函数从来没有被调用过,所以它在调用栈中根本不存在。
除此之外,答案其实在你代码的注释里;
def update_creds(**kwargs):
# inspect.stack()[0][3] gets the name of the function we are currently in
exec(get_new_return(function=inspect.stack()[0][3]))
inspect.stack()[0][3]
的结果会是'update_creds',因为你在调用这个代码的时候正处于这个函数里。所以,当你调用get_new_return()
时,function
这个参数会被设置为'update_creds'。结果就是,get_new_return()
获取的是update_creds()
的源代码。