程式碼物件¶
程式碼物件是 CPython 實現的底層細節。每個程式碼物件都表示尚未繫結到函式的一塊可執行程式碼。
-
type PyCodeObject¶
用於描述程式碼物件的 C 結構體。此型別的欄位隨時可能更改。
-
PyTypeObject PyCode_Type¶
這是
PyTypeObject
的一個例項,表示 Python 程式碼物件。
-
Py_ssize_t PyCode_GetNumFree(PyCodeObject *co)¶
返回程式碼物件中 自由(閉包)變數 的數量。
-
int PyUnstable_Code_GetFirstFree(PyCodeObject *co)¶
- 這是一個不穩定 API。它可能會在次要版本中未經警告而更改。
返回程式碼物件中第一個 自由(閉包)變數 的位置。
3.13 版本中已更改: 作為 不穩定的 C API 的一部分,從
PyCode_GetFirstFree
重新命名。舊名稱已棄用,但會一直可用,直到簽名再次更改。
-
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 版本中已更改: 添加了
qualname
和exceptiontable
引數。3.12 版本中已更改: 作為 不穩定的 C API 的一部分,從
PyCode_New
重新命名。舊名稱已棄用,但會一直可用,直到簽名再次更改。
-
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 版本中已更改: 添加了
qualname
和exceptiontable
引數。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 標識的觀察者,該 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 新版功能.
程式碼物件標誌¶
程式碼物件包含一個標誌位欄位,可以將其作為 co_flags
Python 屬性檢索(例如使用 PyObject_GetAttrString()
),並使用 PyUnstable_Code_New()
和類似函式的 flags 引數進行設定。
名稱以 CO_FUTURE_
開頭的標誌對應於通常透過 future statements 可選擇的功能。這些標誌可以在 PyCompilerFlags.cf_flags
中使用。請注意,許多 CO_FUTURE_
標誌在當前 Python 版本中是強制性的,設定它們沒有效果。
以下標誌可用。有關其含義,請參閱其 Python 等效項的連結文件。
Flag |
含義 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
無影響 ( |
|
|
|
|
|
|
|
|
|
|
|
額外資訊¶
為了支援對幀評估的底層擴充套件,例如外部即時編譯器,可以將任意額外資料附加到程式碼物件。
這些函式是不穩定 C API 層的一部分:此功能是 CPython 實現細節,API 可能會在沒有棄用警告的情況下更改。
-
Py_ssize_t PyUnstable_Eval_RequestCodeExtraIndex(freefunc free)¶
- 這是一個不穩定 API。它可能會在次要版本中未經警告而更改。
返回一個新的不透明索引值,用於向程式碼物件新增資料。
您通常(每個直譯器)呼叫此函式一次,並使用結果與
PyCode_GetExtra
和PyCode_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 更改。