假设我有一个如下定义的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获取函数的名称。我如何通过编程获得它的源代码,就像我上面键入的那样?
当前回答
虽然我通常同意inspect是一个很好的答案,但我不同意您不能获得解释器中定义的对象的源代码。如果从dill中使用dill.source.getsource,则可以获得函数和lambda的源,即使它们是以交互方式定义的。 它还可以从在curry中定义的绑定或未绑定类方法和函数中获取代码…但是,如果没有封闭对象的代码,则可能无法编译该代码。
>>> from dill.source import getsource
>>>
>>> def add(x,y):
... return x+y
...
>>> squared = lambda x:x**2
>>>
>>> print getsource(add)
def add(x,y):
return x+y
>>> print getsource(squared)
squared = lambda x:x**2
>>>
>>> class Foo(object):
... def bar(self, x):
... return x*x+x
...
>>> f = Foo()
>>>
>>> print getsource(f.bar)
def bar(self, x):
return x*x+x
>>>
其他回答
拉法ł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)能够逐级遍历代码的特性。
你可以使用inspect模块来获得完整的源代码。你必须从inspect模块中使用getsource()方法。例如:
import inspect
def get_my_code():
x = "abcd"
return x
print(inspect.getsource(get_my_code))
你可以在下面的链接中查看更多选项。 检索python代码
请注意,只有在单独的一行上给出lambda时,接受的答案才有效。如果您将它作为参数传递给一个函数,并希望检索lambda作为对象的代码,那么问题就会变得有点棘手,因为inspect会给您整行代码。
例如,考虑一个文件test.py:
import inspect
def main():
x, f = 3, lambda a: a + 1
print(inspect.getsource(f))
if __name__ == "__main__":
main()
执行它会给你(注意缩进!):
x, f = 3, lambda a: a + 1
在我看来,要检索lambda的源代码,最好的方法是重新解析整个源文件(通过使用f.__code__.co_filename),并根据行号及其上下文匹配lambda AST节点。
我们必须在契约式设计库契约中做到这一点,因为我们必须解析作为参数传递给装饰器的lambda函数。这里粘贴的代码太多了,所以看一下这个函数的实现。
只是使用foo??还是? ? foo。
如果你正在使用IPython,那么你需要输入foo??还是? ?Foo来查看完整的源代码。要只看到函数中的文档字符串,请使用foo?或? foo。这也适用于Jupyter笔记本电脑。
In [19]: foo??
Signature: foo(arg1, arg2)
Source:
def foo(arg1,arg2):
#do something with args
a = arg1 + arg2
return a
File: ~/Desktop/<ipython-input-18-3174e3126506>
Type: function
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