如何获取Python函数的源代码?

如何获取Python函数的源代码?,python,function,Python,Function,假设我有一个Python函数,定义如下: def foo(arg1,arg2): #do something with args a = arg1 + arg2 return a 我可以使用foo.func\u name获取函数名。如何以编程方式获取其源代码,正如我在上面键入的那样?具有从python对象检索源代码的方法。但似乎只有当源位于文件中时,它才起作用。如果你有这个,我想你就不需要从这个对象中获取源了 使用Python 3.6进行以下测试inspect.get

假设我有一个Python函数,定义如下:

def foo(arg1,arg2):
    #do something with args
    a = arg1 + arg2
    return a
我可以使用
foo.func\u name
获取函数名。如何以编程方式获取其源代码,正如我在上面键入的那样?

具有从python对象检索源代码的方法。但似乎只有当源位于文件中时,它才起作用。如果你有这个,我想你就不需要从这个对象中获取源了


使用Python 3.6进行以下测试
inspect.getsource(foo)

导入检查
def foo(arg1、arg2):
#用args做点什么
a=arg1+arg2
归还
source_foo=inspect.getsource(foo)#foo是正常功能
打印(源文件)
source_max=inspect.getsource(max)#max是一个内置函数
打印(源\最大值)
这第一次打印:

def foo(arg1、arg2): #用args做点什么 a=arg1+arg2 归还 然后在
inspect.getsource(max)
上失败,出现以下错误:

TypeError: <built-in function max> is not a module, class, method, function, traceback, frame, or code object
TypeError:不是模块、类、方法、函数、回溯、帧或代码对象
具有从python对象检索源代码的方法。但似乎只有当源位于文件中时,它才起作用。如果你有这个,我想你就不需要从这个对象中获取源了


使用Python 3.6进行以下测试
inspect.getsource(foo)

导入检查
def foo(arg1、arg2):
#用args做点什么
a=arg1+arg2
归还
source_foo=inspect.getsource(foo)#foo是正常功能
打印(源文件)
source_max=inspect.getsource(max)#max是一个内置函数
打印(源\最大值)
这第一次打印:

def foo(arg1、arg2): #用args做点什么 a=arg1+arg2 归还 然后在
inspect.getsource(max)
上失败,出现以下错误:

TypeError: <built-in function max> is not a module, class, method, function, traceback, frame, or code object
TypeError:不是模块、类、方法、函数、回溯、帧或代码对象

我相信变量名不会存储在pyc/pyd/pyo文件中,因此如果没有源文件,就无法检索准确的代码行。

我相信变量名不会存储在pyc/pyd/pyo文件中,因此,如果没有源文件,则无法检索准确的代码行。

如果该函数来自文件系统上可用的源文件,则可能会有所帮助:

如果
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                

但我认为,如果函数是从字符串、流或从已编译文件导入的,则无法检索其源代码。

如果函数来自文件系统上可用的源文件,则可能会有所帮助:

如果
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                

但是我相信,如果函数是从字符串、流或从已编译的文件中编译的,那么您就无法检索其源代码。

如果您自己严格定义函数,并且它是一个相对较短的定义,那么没有依赖项的解决方案将是在字符串中定义函数并分配eval()将表达式转换为函数

例如

然后可选地将原始代码附加到函数:

func.source = funcstring

如果您自己严格定义函数,而且定义相对较短,那么没有依赖项的解决方案是在字符串中定义函数,并将表达式的eval()赋值给您的函数

例如

然后可选地将原始代码附加到函数:

func.source = funcstring

如果源代码不可用,
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

如果源代码不可用,
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
是一个很好的答案,但我不同意您不能获得在解释器中定义的对象的源代码。如果使用
dill.source.getsource
from,则可以获取函数和lambda的源代码,即使它们是以交互方式定义的。 它还可以从curries中定义的绑定或未绑定类方法和函数中获取的代码。。。但是,如果没有封闭对象的代码,您可能无法编译该代码

>>> 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

>>> 

虽然我大体上同意
inspect
是一个很好的答案,但我不同意您不能获得在解释器中定义的对象的源代码。如果使用
dill.source.getsource
from,则可以获取函数和lambda的源代码,即使它们是以交互方式定义的。 它还可以从curries中定义的绑定或未绑定类方法和函数中获取的代码。。。但是,如果没有封闭对象的代码,您可能无法编译该代码

>>> 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

>>> 

要扩展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
。但是,当从源文件导入代码时,这两种方法都可以。要展开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
。但是,当从源文件导入代码时,这两种方法都应该很好。

如果您使用的是IPython,那么您需要键入“foo??”

[19]中的
:foo??
签名:foo(arg1、arg2)
资料来源:
def foo(arg1、arg2):
#用args做点什么
a=arg1+arg2
归还
文件:~/Desktop/
类型:功能

如果您使用的是IPython,则需要键入“foo??”

[19]中的
:foo??
签名:foo(arg1、arg2)
资料来源:
def foo(arg1、arg2):
#用args做点什么
a=arg1+arg2
归还
文件:~/Desktop/
类型:功能
总结一下:

import inspect
print( "".join(inspect.getsourcelines(foo)[0]))
总结如下:

import inspect
print( "".join(inspect.getsourcelines(foo)[0]))

您可以使用
inspect
模块获取完整的源代码。您必须使用
getsource()
方法从
inspect
模块进行检查。例如:

import inspect

def get_my_code():
    x = "abcd"
    return x

print(inspect.getsource(get_my_code))
您可以在下面的链接上查看更多选项。 你可以