程式碼物件

程式碼物件是 CPython 實現的底層細節。每一個都代表一塊尚未繫結到函式中的可執行程式碼。

type PyCodeObject

用於描述程式碼物件的 C 結構。此型別的欄位隨時可能更改。

PyTypeObject PyCode_Type

這是 PyTypeObject 的一個例項,代表 Python 程式碼物件

int PyCode_Check(PyObject *co)

如果 co 是一個 程式碼物件,則返回 true。此函式總是成功。

Py_ssize_t PyCode_GetNumFree(PyCodeObject *co)

返回程式碼物件中 自由(閉包)變數 的數量。

int PyUnstable_Code_GetFirstFree(PyCodeObject *co)
這是 不穩定 API。它可能在小版本更新中更改,恕不另行通知。

返回程式碼物件中第一個 自由(閉包)變數 的位置。

在 3.13 版本中更改:PyCode_GetFirstFree 重新命名,作為 不穩定 C API 的一部分。舊名稱已棄用,但會保留到簽名再次更改為止。

PyCodeObject *PyUnstable_Code_New(int argcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)
這是 不穩定 API。它可能在小版本更新中更改,恕不另行通知。

返回一個新的程式碼物件。如果您需要一個虛擬程式碼物件來建立幀,請使用 PyCode_NewEmpty() 代替。

由於位元組碼的定義經常更改,直接呼叫 PyUnstable_Code_New() 可能會將您繫結到特定的 Python 版本。

此函式的許多引數以複雜的方式相互依賴,這意味著值的細微更改很可能導致執行不正確或 VM 崩潰。僅在極其謹慎的情況下使用此功能。

在 3.11 版本中更改:添加了 qualnameexceptiontable 引數。

在 3.12 版本中更改:PyCode_New 重新命名,作為 不穩定 C API 的一部分。舊名稱已棄用,但會保留到簽名再次更改為止。

PyCodeObject *PyUnstable_Code_NewWithPosOnlyArgs(int argcount, int posonlyargcount, int kwonlyargcount, int nlocals, int stacksize, int flags, PyObject *code, PyObject *consts, PyObject *names, PyObject *varnames, PyObject *freevars, PyObject *cellvars, PyObject *filename, PyObject *name, PyObject *qualname, int firstlineno, PyObject *linetable, PyObject *exceptiontable)
這是 不穩定 API。它可能在小版本更新中更改,恕不另行通知。

類似於 PyUnstable_Code_New(),但為僅限位置引數添加了額外的“posonlyargcount”。適用於 PyUnstable_Code_New 的注意事項也適用於此函式。

在 3.8 版本中新增:作為 PyCode_NewWithPosOnlyArgs

在 3.11 版本中更改:添加了 qualnameexceptiontable 引數。

3.12 版本更改: 重新命名為 PyUnstable_Code_NewWithPosOnlyArgs。舊名稱已棄用,但會保留可用,直到簽名再次更改。

PyCodeObject *PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
返回值:新引用。

返回一個新的空程式碼物件,其中包含指定的檔名、函式名稱和首行行號。如果執行生成的程式碼物件,則會引發 Exception 異常。

int PyCode_Addr2Line(PyCodeObject *co, int byte_offset)

返回發生在 byte_offset 或之前並在其之後結束的指令的行號。 如果您只需要幀的行號,請改用 PyFrame_GetLineNumber()

為了高效地迭代程式碼物件中的行號,請使用 PEP 626 中描述的 API

int PyCode_Addr2Location(PyObject *co, int byte_offset, int *start_line, int *start_column, int *end_line, int *end_column)

將傳遞的 int 指標設定為 byte_offset 處指令的原始碼行和列號。當任何特定元素的資訊不可用時,將值設定為 0

如果函式成功,則返回 1,否則返回 0。

在 3.11 版本中新增。

PyObject *PyCode_GetCode(PyCodeObject *co)

等效於 Python 程式碼 getattr(co, 'co_code')。 返回對 PyBytesObject 的強引用,該引用表示程式碼物件中的位元組碼。 如果出錯,則返回 NULL 並引發異常。

PyBytesObject 可能會由直譯器按需建立,並且不一定表示 CPython 實際執行的位元組碼。此函式的主要用例是偵錯程式和效能分析器。

在 3.11 版本中新增。

PyObject *PyCode_GetVarnames(PyCodeObject *co)

等效於 Python 程式碼 getattr(co, 'co_varnames')。 返回對包含區域性變數名稱的 PyTupleObject 的新引用。 如果出錯,則返回 NULL 並引發異常。

在 3.11 版本中新增。

PyObject *PyCode_GetCellvars(PyCodeObject *co)

等效於 Python 程式碼 getattr(co, 'co_cellvars')。 返回對包含巢狀函式引用的區域性變數名稱的 PyTupleObject 的新引用。 如果出錯,則返回 NULL 並引發異常。

在 3.11 版本中新增。

PyObject *PyCode_GetFreevars(PyCodeObject *co)

等效於 Python 程式碼 getattr(co, 'co_freevars')。 返回對包含自由(閉包)變數名稱的 PyTupleObject 的新引用。 如果出錯,則返回 NULL 並引發異常。

在 3.11 版本中新增。

int PyCode_AddWatcher(PyCode_WatchCallback callback)

將 *callback* 註冊為當前直譯器的程式碼物件監視器。 返回一個 ID,該 ID 可以傳遞給 PyCode_ClearWatcher()。如果發生錯誤(例如,沒有更多可用的監視器 ID),則返回 -1 並設定異常。

在 3.12 版本中新增。

int PyCode_ClearWatcher(int watcher_id)

清除由 *watcher_id* 標識的監視器,該監視器先前由當前直譯器的 PyCode_AddWatcher() 返回。 成功時返回 0,或者在出錯時返回 -1 並設定異常(例如,如果給定的 *watcher_id* 從未註冊)。

在 3.12 版本中新增。

type PyCodeEvent

可能的程式碼物件監視器事件的列舉: - PY_CODE_EVENT_CREATE - PY_CODE_EVENT_DESTROY

在 3.12 版本中新增。

typedef int (*PyCode_WatchCallback)(PyCodeEvent event, PyCodeObject *co)

程式碼物件監視器回撥函式的型別。

如果 *event* 是 PY_CODE_EVENT_CREATE,則在 co 完全初始化後呼叫回撥。 否則,在銷燬 *co* 發生之前呼叫回撥,因此可以檢查 *co* 的先前狀態。

如果 *event* 是 PY_CODE_EVENT_DESTROY,則在回撥中引用即將被銷燬的程式碼物件將會使其復活,並阻止其此時被釋放。 當復活的物件稍後被銷燬時,屆時處於活動狀態的任何監視器回撥將再次被呼叫。

此 API 的使用者不應依賴於內部執行時實現的細節。這些細節可能包括但不限於程式碼物件建立和銷燬的確切順序和時間。儘管這些細節的更改可能會導致觀察者可觀察到的差異(包括是否呼叫回撥),但這不會改變正在執行的 Python 程式碼的語義。

如果回撥設定了異常,則必須返回 -1;此異常將使用 PyErr_WriteUnraisable() 列印為不可引發的異常。否則,它應返回 0

在進入回撥時,可能已經存在一個待處理的異常設定。在這種情況下,回撥應返回 0,並且仍然設定相同的異常。這意味著回撥可能不會呼叫任何其他可以設定異常的 API,除非它先儲存並清除異常狀態,然後在返回之前恢復它。

在 3.12 版本中新增。

額外資訊

為了支援對幀求值的底層擴充套件,例如外部即時編譯器,可以將任意額外資料附加到程式碼物件。

這些函式是不穩定的 C API 層的一部分:此功能是 CPython 實現細節,API 可能會在沒有棄用警告的情況下發生更改。

Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)
這是 不穩定 API。它可能在小版本更新中更改,恕不另行通知。

返回一個用於向程式碼物件新增資料的新不透明索引值。

您通常(每個直譯器)呼叫此函式一次,並使用結果與 PyCode_GetExtraPyCode_SetExtra 一起操作單個程式碼物件上的資料。

如果 free 不為 NULL:當代碼物件被釋放時,將在新索引下儲存的非 NULL 資料上呼叫 free。在儲存 PyObject 時,請使用 Py_DecRef()

3.6 版本新增: 作為 _PyEval_RequestCodeExtraIndex

在 3.12 版本中更改: 重新命名為 PyUnstable_Eval_RequestCodeExtraIndex。舊的私有名稱已棄用,但在 API 更改之前仍然可用。

int PyUnstable_Code_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
這是 不穩定 API。它可能在小版本更新中更改,恕不另行通知。

extra 設定為給定索引下儲存的額外資料。成功時返回 0。失敗時設定異常並返回 -1。

如果在該索引下未設定任何資料,則將 extra 設定為 NULL 並返回 0,而不設定異常。

3.6 版本新增: 作為 _PyCode_GetExtra

在 3.12 版本中更改: 重新命名為 PyUnstable_Code_GetExtra。舊的私有名稱已棄用,但在 API 更改之前仍然可用。

int PyUnstable_Code_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
這是 不穩定 API。它可能在小版本更新中更改,恕不另行通知。

將給定索引下儲存的額外資料設定為 extra。成功時返回 0。失敗時設定異常並返回 -1。

3.6 版本新增: 作為 _PyCode_SetExtra

在 3.12 版本中更改: 重新命名為 PyUnstable_Code_SetExtra。舊的私有名稱已棄用,但在 API 更改之前仍然可用。