如何从 Python 对象中检索源代码?


使用inspect模块,您可以检索Python 函数、方法、类或模块的源代码。以下示例演示了如何检索函数的源代码 -

示例

import inspect
def my_function(x, y):
   return x + y
source_code = inspect.getsource(my_function)
print(source_code)

输出

def my_function(x, y):
   return x + y

此代码定义了一个简单的函数my_function,它接受两个参数并返回这些参数的总和。然后,我们使用inspect.getsource()函数检索my_function函数的源代码并将其存储在源代码变量中。最后,源代码输出到控制台。

inspect.getsource()函数通过读取其定义所在文件的函数的源代码来工作。它将函数的整个源代码(包括源代码中存在的任何注释或空行)作为字符串返回。

inspect.getsourcefile()函数也可用于检索包含函数或模块源代码的文件名。如果您需要找到包含特定函数或模块的文件,这将非常有用。

以下示例演示了如何检索包含函数源代码的文件名 -

示例

import inspect
def my_function(x, y):
   return x + y
source_file = inspect.getsourcefile(my_function)
print(source_file)

输出

/home/cg/root/79120/main.py

此代码定义了与之前相同的my_function函数,并使用inspect.getsourcefile()函数检索包含函数源代码的文件名。此函数将文件名作为字符串返回,而不是实际的源代码。

inspect模块提供了多个用于检索有关Python 对象(包括其源代码)的信息的函数。以下是一些其他示例 -

要检索类方法的源代码,请在方法本身上调用inspect.getsource() -

示例

import inspect
class MyClass:
   def my_method(self, x, y):
      return x + y
source_code = inspect.getsource(MyClass.my_method)
print(source_code)

输出

def my_method(self, x, y):
   return x + y

在此示例中,类MyClass有一个名为my_method的方法,它接受两个参数并返回它们的总和。然后使用inspect.getsource()检索MyClass.my_method方法的源代码。

要完整检索模块的源代码,请在模块本身上使用inspect.getsource()函数 -

示例

import inspect
import my_module
source_code = inspect.getsource(my_module)
print(source_code)

在此示例中,我们导入my_module模块并使用inspect.getsource检索其源代码。

您还可以使用inspect.getfile函数获取保存模块、类或函数源代码的文件名。与inspect.getsourcefile类似,此函数将文件名作为字符串返回。此示例演示了如何使用inspect.getfile检索模块的文件名 -

示例

import inspect
import my_module
source_file = inspect.getfile(my_module)
print(source_file)

此代码导入my_module模块并使用inspect.getfile()检索源代码文件的名称。请注意,此函数返回文件的绝对路径。

dis模块是另一种检索Python函数源代码的方法。dis模块为您提供了Python字节码的反汇编程序,您可以使用它查看函数的字节码指令。通过反编译字节码,可以更全面地了解函数是如何工作的,包括操作的确切顺序。

以下是如何使用dis模块检索函数的字节码指令的示例 -

示例

import dis
def my_function(x, y):
   return x + y
bytecode = dis.Bytecode(my_function)
for instruction in bytecode:
   print(instruction)

输出

Instruction(opname='LOAD_FAST', opcode=124, arg=0, argval='x', argrepr='x', offset=0, starts_line=3, is_jump_target=False)
Instruction(opname='LOAD_FAST', opcode=124, arg=1, argval='y', argrepr='y', offset=2, starts_line=None, is_jump_target=False)
Instruction(opname='BINARY_ADD', opcode=23, arg=None, argval=None, argrepr='', offset=4, starts_line=None, is_jump_target=False)
Instruction(opname='RETURN_VALUE', opcode=83, arg=None, argval=None, argrepr='', offset=6, starts_line=None, is_jump_target=False)

在此示例中,定义了一个名为my_function的简单函数,它接受两个参数并返回它们的总和。然后通过将my_function函数传递给dis.Bytecode函数Object() { [native code] } 创建一个dis.Bytecode对象。这让我们可以查看函数的字节码指令在被分解后的样子。然后,我们可以使用for循环遍历这些指令并将它们打印到控制台。

此代码将返回一系列dis.Instruction对象,它们表示函数的字节码指令。每个dis.Instruction对象都包含诸如opname(字节码指令的名称)、argval(指令的参数)和offset(指令在函数的字节码中的字节偏移量)之类的属性。通过查看这些属性,您可以了解函数工作方式的所有信息。

请注意,dis模块可能非常底层,可能不适用于所有用例。但是,如果您需要全面了解函数的工作方式,它可能是一个有用的工具。我们使用inspect模块的getsource()方法获取函数的源代码。

示例

inspect.getsource(object)

这将返回对象源代码的文本。参数可以是模块、类、方法、函数、回溯、帧或代码对象。将源代码作为单个字符串返回。如果无法检索源代码,则会生成IOError。

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

以下是我们如何导入inspect模块并检索给定脚本的源代码

示例

#baz.py
import inspect
class foo:
   def bar():
      print ('Hello')
print(inspect.getsource(foo))

输出

class foo:
   def bar():
      print ('Hello')

更新于:2023年8月31日

14K+ 浏览量

启动您的职业生涯

通过完成课程获得认证

开始
广告