如何從 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+ 瀏覽量

啟動您的職業生涯

透過完成課程獲得認證

開始
廣告