如何從 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')