我可以知道从哪里调用/调用函数吗?
Posted
技术标签:
【中文标题】我可以知道从哪里调用/调用函数吗?【英文标题】:Can I know from where a function has been invoked/called? 【发布时间】:2021-08-07 04:38:11 【问题描述】:我开始使用 Python 3 进行编程。我想知道是否有任何函数或方法可以让我知道从哪个位置(也许是从哪一行)调用了该函数.
例如,如果我有以下代码...
1 def foo():
2 print("Hi!")
3
4 def suma(a, b):
5 return a+b
6
7
8 def main():
9 foo()
10 suma(3,6)
11
12
13 if __name__ == "__main__":
14 main()
15 else:
16 print("Function main() not exist")
17
不知何故知道函数:
foo
:在第 1 行定义。
它已在第 9 行从main
调用
suma
:在第 4 行定义。
已在第 10 行从main
调用。
是否有一些功能可以做到这一点或类似的功能?
可能是这样的:
foo.__ code __. co_nlocals
suma.__ code __. co_nlocals
但是有了前面提到的。
【问题讨论】:
也许traceback-module 可以帮助你 您能否详细说明您的实际用例是什么?为什么需要这样做?或者更确切地说,你为什么认为你需要这样做?我这样表述的原因是因为你提到你刚刚开始 - 初学者经常问他们对问题的想象方法的问题,而不是问题本身。如果您分享用例,有人可能会建议另一种方法。 作为旁注,第 15 行中的“else:”子句毫无意义。如果您调用一个不存在的函数,解释器将非常乐意告诉您,并提供有用的错误消息和回溯。永远不要检查您不准备处理的错误情况。 您可以使用调试器知道哪个是调用者。例如,PyCharmelse
子句是错误的 - 无论__name__ == "__main__"
是否存在,main
都将存在。这不是 if __name__ == "__main__"
检查的用途。 if __name__ == "__main__"
检查我们是否应该运行文件的脚本功能,而不是我们是否可以这样做。
【参考方案1】:
定义函数的行号。
使用:inspect.getsourcelines(THE_NAME_OF_YOUR_FUNCTION)[1]
函数所在的行。
使用:called.inspect.stack()[1][2]
调用/调用函数。
使用:inspect.stack()[1][3]
(可选)包含它的模块。
使用:THE_NAME_OF_YOUR_FUNCTION.__module__
举个例子……(我添加了一个额外的函数X)
import inspect
def foo(msg):
print(msg)
###▼ YOUR INSPECTION CODE ▼###
print("\t«»\tLine number in which the function is defined.".
format(inspect.getsourcelines(foo)[1]))
print("\t«»\tLine from which the function has been called.".
format(inspect.stack()[1][2]))
print("\t«»\tInvoking/calling function.".format(inspect.stack()[1][3]))
print("\t«»\tModule in which it is contained.\n".format(foo.__module__))
def suma(a, b):
foo("Call from [suma()], on the line [14]")
return a+b
def difference(a, b):
foo("Call from [difference()], on the line [18]")
return a-b
def main():
foo("Call from [main()], on the line [22]")
suma(3,6)
foo("Call from [main()], on the line [24]")
difference(5,2)
if __name__ == "__main__":
main()
如果我们列出前面的行,代码如下:
01 import inspect
02
03 def foo(msg):
04 print(msg)
05 ###▼ YOUR INSPECTION CODE ▼###
06 print("\t«»\tLine number in which the function is defined.".
07 format(inspect.getsourcelines(foo)[1]))
08 print("\t«»\tLine from which the function has been called.".
09 format(inspect.stack()[1][2]))
10 print("\t«»\tInvoking/calling function.".format(inspect.stack()[1][3]))
11 print("\t«»\tModule in which it is contained.\n".format(foo.__module__))
12
13 def suma(a, b):
14 foo("Call from [suma()], on the line [14]")
15 return a+b
16
17 def difference(a, b):
18 foo("Call from [difference()], on the line [18]")
19 return a-b
20
21 def main():
22 foo("Call from [main()], on the line [22]")
23 suma(3,6)
24 foo("Call from [main()], on the line [24]")
25 difference(5,2)
26
27 if __name__ == "__main__":
28 main()
你会得到这样的结果:
Call from [main()], on the line [22]
«3» Line number in which the function is defined.
«22» Line from which the function has been called.
«main» Invoking/calling function.
«__main__» Module in which it is contained.
Call from [suma()], on the line [14]
«3» Line number in which the function is defined.
«14» Line from which the function has been called.
«suma» Invoking/calling function.
«__main__» Module in which it is contained.
Call from [main()], on the line [24]
«3» Line number in which the function is defined.
«24» Line from which the function has been called.
«main» Invoking/calling function.
«__main__» Module in which it is contained.
Call from [difference()], on the line [18]
«3» Line number in which the function is defined.
«18» Line from which the function has been called.
«difference» Invoking/calling function.
«__main__» Module in which it is contained.
【讨论】:
【参考方案2】:inspect
模块是您想要的方式(特别是 .getsourcelines()
方法)。
def foo():
print("Hi!")
def suma(a, b):
return a+b
import inspect
print(inspect.getsourcelines(foo))
print(inspect.getsourcelines(suma))
(['def foo():\n', ' print("Hi!")\n'], 1) (['def suma(a, b):\n', ' return a+b\n'], 4)
您会看到结果是一个元组,其中第一个元素是函数的源,第二个元素是定义函数的行。
如果您也需要,还有一个等效的 getsourcefile 方法来获取文件。
【讨论】:
inspect.getsourcelines
没有说明函数从哪里调用。
我很高兴就问题的另一半提出建议。当我最初发布此内容时,其他人有一个堆栈解决方案,可以解决问题的那一部分。我只是想解决“foo:它在第 1 行中定义”。部分。以上是关于我可以知道从哪里调用/调用函数吗?的主要内容,如果未能解决你的问题,请参考以下文章