假设我有一个如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
我可以使用foo.func_name获取函数的名称。我如何通过编程获得它的源代码,就像我上面键入的那样?
假设我有一个如下定义的Python函数:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
我可以使用foo.func_name获取函数的名称。我如何通过编程获得它的源代码,就像我上面键入的那样?
当前回答
拉法łDowgird朋友与答案:
我相信,如果函数是从字符串、流或从编译文件导入的,那么你就不能检索它的源代码。
但是,可以检索从字符串编译的函数的源代码,前提是编译代码还向lineecache添加了一个条目。缓存dict类型:
import linecache
import inspect
script = '''
def add_nums(a, b):
return a + b
'''
bytecode = compile(script, 'unique_filename', 'exec')
tmp = {}
eval(bytecode, {}, tmp)
add_nums = tmp["add_nums"]
linecache.cache['unique_filename'] = (
len(script),
None,
script.splitlines(True),
'unique_filename',
)
print(inspect.getsource(add_nums))
# prints:
# """
# def add_nums(a, b):
# return a + b
# """
这就是attrs库如何自动为类创建各种方法,给定一组类期望初始化的属性。点击这里查看他们的源代码。正如源代码所解释的,这是一个主要用于使调试器(如PDB)能够逐级遍历代码的特性。
其他回答
扩展一下runeh的回答:
>>> def foo(a):
... x = 2
... return x + a
>>> import inspect
>>> inspect.getsource(foo)
u'def foo(a):\n x = 2\n return x + a\n'
print inspect.getsource(foo)
def foo(a):
x = 2
return x + a
编辑:正如@0sh指出的那样,这个例子使用ipython工作,而不是纯python。但是,当从源文件导入代码时,在这两种情况下都应该没问题。
如果源代码不可用,Dis是你的朋友:
>>> import dis
>>> def foo(arg1,arg2):
... #do something with args
... a = arg1 + arg2
... return a
...
>>> dis.dis(foo)
3 0 LOAD_FAST 0 (arg1)
3 LOAD_FAST 1 (arg2)
6 BINARY_ADD
7 STORE_FAST 2 (a)
4 10 LOAD_FAST 2 (a)
13 RETURN_VALUE
如果函数来自文件系统中可用的源文件,那么inspect.getsource(foo)可能会有帮助:
如果foo被定义为:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
然后:
import inspect
lines = inspect.getsource(foo)
print(lines)
返回:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
但我相信,如果函数是从字符串、流或从编译文件导入的,那么你就不能检索它的源代码。
我相信变量名没有存储在pyc/pyd/pyo文件中,因此如果没有源文件,就无法检索准确的代码行。
inspect模块有从python对象中检索源代码的方法。但是,似乎只有当源文件位于文件中时,它才有效。如果你有这个,我猜你就不需要从对象中获取源了。
下面使用Python 3.6测试inspect.getsource(foo):
import inspect
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
source_foo = inspect.getsource(foo) # foo is normal function
print(source_foo)
source_max = inspect.getsource(max) # max is a built-in function
print(source_max)
这是第一次印刷:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
然后在inspect.getsource(max)上失败,并出现以下错误:
TypeError: <built-in function max> is not a module, class, method, function, traceback, frame, or code object