解析引數和構建值

這些函式在建立您自己的擴充套件函式和方法時非常有用。更多資訊和示例可以在擴充套件和嵌入 Python 直譯器中找到。

前三個描述的函式,PyArg_ParseTuple()PyArg_ParseTupleAndKeywords()PyArg_Parse(),都使用格式字串來告知函式有關預期引數的資訊。這些函式的格式字串使用相同的語法。

解析引數

格式字串由零個或多個“格式單元”組成。格式單元描述一個 Python 物件;它通常是一個字元或一個帶括號的格式單元序列。除少數例外,非帶括號序列的格式單元通常對應於這些函式的單個地址引數。在以下描述中,帶引號的形式是格式單元;(圓)括號中的條目是與格式單元匹配的 Python 物件型別;[方]括號中的條目是應傳遞其地址的 C 變數的型別。

字串和緩衝區

注意

在 Python 3.12 及更早版本中,必須在包含 Python.h 之前定義宏 PY_SSIZE_T_CLEAN,才能使用下面解釋的所有格式的 # 變體(s#y# 等)。這在 Python 3.13 及更高版本中不是必需的。

這些格式允許將物件作為連續的記憶體塊訪問。您無需為返回的 Unicode 或位元組區域提供原始儲存。

除非另有說明,否則緩衝區不是以 NUL 結尾的。

有三種方法可以將字串和緩衝區轉換為 C

  • 諸如 y*s* 之類的格式會填充 Py_buffer 結構。 這會鎖定底層緩衝區,以便呼叫者隨後可以使用該緩衝區,即使在 Py_BEGIN_ALLOW_THREADS 塊內,也不會有可變資料被調整大小或銷燬的風險。 因此,**您必須呼叫** PyBuffer_Release(),在您完成處理資料之後(或在任何提前中止的情況下)。

  • eses#etet# 格式分配結果緩衝區。 **您必須呼叫** PyMem_Free(),在您完成處理資料之後(或在任何提前中止的情況下)。

  • 其他格式接受 str 或只讀的 類位元組物件,例如 bytes,併為其緩衝區提供一個 const char * 指標。在這種情況下,緩衝區是“借用”的:它由相應的 Python 物件管理,並共享此物件的生命週期。您無需自己釋放任何記憶體。

    為確保可以安全地借用底層緩衝區,物件的 PyBufferProcs.bf_releasebuffer 欄位必須為 NULL。 這不允許使用常見的可變物件,例如 bytearray,但也禁止使用某些只讀物件,例如 bytesmemoryview

    除了此 bf_releasebuffer 要求之外,沒有檢查來驗證輸入物件是否是不可變的(例如,它是否會響應可寫緩衝區的請求,或者另一個執行緒是否可以更改資料)。

s (str) [const char *]

將 Unicode 物件轉換為指向字元字串的 C 指標。指向現有字串的指標儲存在您傳遞其地址的字元指標變數中。 C 字串以 NUL 結尾。Python 字串不得包含嵌入的空程式碼點;如果包含,則會引發 ValueError 異常。Unicode 物件使用 'utf-8' 編碼轉換為 C 字串。如果此轉換失敗,則會引發 UnicodeError

注意

此格式不接受 類位元組物件。如果您想接受檔案系統路徑並將它們轉換為 C 字元字串,則最好使用帶有 PyUnicode_FSConverter() 作為*轉換器*的 O& 格式。

在 3.5 版本中更改:之前,當在 Python 字串中遇到嵌入的空程式碼點時,會引發 TypeError

s* (str類位元組物件) [Py_buffer]

此格式接受 Unicode 物件以及類位元組物件。 它會填充呼叫者提供的 Py_buffer 結構。 在這種情況下,生成的 C 字串可能包含嵌入的 NUL 位元組。 Unicode 物件使用 'utf-8' 編碼轉換為 C 字串。

s# (str, 只讀的 類位元組物件) [const char *, Py_ssize_t]

類似於 s*,但它提供一個借用的緩衝區。結果儲存到兩個 C 變數中,第一個是指向 C 字串的指標,第二個是其長度。該字串可能包含嵌入的空位元組。Unicode 物件使用 'utf-8' 編碼轉換為 C 字串。

z (strNone) [const char *]

類似於 s,但 Python 物件也可能是 None,在這種情況下,C 指標設定為 NULL

z* (str類位元組物件None) [Py_buffer]

類似於 s*,但 Python 物件也可能是 None,在這種情況下,Py_buffer 結構的 buf 成員設定為 NULL

z# (str、只讀的 類位元組物件None) [const char *, Py_ssize_t]

類似於 s#,但 Python 物件也可以是 None,在這種情況下,C 指標會被設定為 NULL

y (只讀的類位元組物件) [const char *]

此格式將類位元組物件轉換為 C 指標,指向一個借用的字串;它不接受 Unicode 物件。位元組緩衝區不能包含嵌入的空位元組;如果包含,則會引發 ValueError 異常。

在 3.5 版本中更改: 之前,如果在位元組緩衝區中遇到嵌入的空位元組,會引發 TypeError

y* (類位元組物件) [Py_buffer]

s* 的變體不接受 Unicode 物件,只接受類位元組物件。這是接受二進位制資料的推薦方式。

y# (只讀的類位元組物件) [const char *, Py_ssize_t]

s# 的變體不接受 Unicode 物件,只接受類位元組物件。

S (bytes) [PyBytesObject *]

要求 Python 物件是 bytes 物件,不嘗試任何轉換。如果物件不是 bytes 物件,則會引發 TypeError。C 變數也可以宣告為 PyObject*

Y (bytearray) [PyByteArrayObject *]

要求 Python 物件是 bytearray 物件,不嘗試任何轉換。如果物件不是 bytearray 物件,則會引發 TypeError。C 變數也可以宣告為 PyObject*

U (str) [PyObject *]

要求 Python 物件是 Unicode 物件,不嘗試任何轉換。如果物件不是 Unicode 物件,則會引發 TypeError。C 變數也可以宣告為 PyObject*

w* (可讀寫的類位元組物件) [Py_buffer]

此格式接受任何實現可讀寫緩衝區介面的物件。它會填充呼叫者提供的 Py_buffer 結構。緩衝區可能包含嵌入的空位元組。呼叫者在完成緩衝區操作後必須呼叫 PyBuffer_Release()

es (str) [const char *encoding, char **buffer]

s 的變體用於將 Unicode 編碼為字元緩衝區。它只適用於不包含嵌入 NUL 位元組的編碼資料。

此格式需要兩個引數。第一個引數僅用作輸入,必須是一個指向以 NUL 結尾的編碼名稱字串的 const char*,或者為 NULL,在這種情況下會使用 'utf-8' 編碼。如果 Python 不知道指定的編碼,則會引發異常。第二個引數必須是 char**;它引用的指標的值將被設定為包含引數文字內容的緩衝區。文字將使用第一個引數指定的編碼進行編碼。

PyArg_ParseTuple() 將分配所需大小的緩衝區,將編碼資料複製到此緩衝區,並調整 *buffer 以引用新分配的儲存空間。呼叫者有責任在使用後呼叫 PyMem_Free() 來釋放已分配的緩衝區。

et (str, bytesbytearray) [const char *encoding, char **buffer]

es 相同,不同之處在於位元組字串物件會直接傳遞,不進行重新編碼。相反,實現會假定位元組字串物件使用作為引數傳入的編碼。

es# (str) [const char *encoding, char **buffer, Py_ssize_t *buffer_length]

s# 的變體用於將 Unicode 編碼為字元緩衝區。與 es 格式不同,此變體允許輸入包含 NUL 字元的資料。

它需要三個引數。第一個引數僅用作輸入,必須是一個指向以 NUL 結尾的編碼名稱字串的 const char*,或者為 NULL,在這種情況下會使用 'utf-8' 編碼。如果 Python 不知道指定的編碼,則會引發異常。第二個引數必須是 char**;它引用的指標的值將被設定為包含引數文字內容的緩衝區。文字將使用第一個引數指定的編碼進行編碼。第三個引數必須是指向整數的指標;引用的整數將被設定為輸出緩衝區中的位元組數。

有兩種操作模式

如果 *buffer 指向一個 NULL 指標,函式將分配所需大小的緩衝區,將編碼資料複製到此緩衝區,並將 *buffer 設定為引用新分配的儲存空間。呼叫者有責任在使用後呼叫 PyMem_Free() 來釋放已分配的緩衝區。

如果 *buffer 指向一個非 NULL 指標(已分配的緩衝區),PyArg_ParseTuple() 將使用此位置作為緩衝區,並將 *buffer_length 的初始值解釋為緩衝區大小。然後,它會將編碼資料複製到緩衝區並以 NUL 結尾。如果緩衝區不夠大,則會設定 ValueError

在這兩種情況下,*buffer_length 都會被設定為編碼資料的長度,不包括結尾的 NUL 位元組。

et# (str, bytesbytearray) [const char *encoding, char **buffer, Py_ssize_t *buffer_length]

es# 相同,不同之處在於位元組字串物件會直接傳遞,不進行重新編碼。相反,實現會假定位元組字串物件使用作為引數傳入的編碼。

在 3.12 版本中更改: 刪除了 uu#ZZ#,因為它們使用了舊式的 Py_UNICODE* 表示形式。

數字

b (int) [unsigned char]

將一個非負 Python 整數轉換為一個無符號的小整數,儲存在 C unsigned char 中。

B (int) [unsigned char]

將一個 Python 整數轉換為一個小整數,不進行溢位檢查,儲存在 C unsigned char 中。

h (int) [short int]

將 Python 整數轉換為 C short int

H (int) [unsigned short int]

將 Python 整數轉換為 C unsigned short int,不進行溢位檢查。

i (int) [int]

將 Python 整數轉換為普通的 C int

I (int) [unsigned int]

將 Python 整數轉換為 C unsigned int,不進行溢位檢查。

l (int) [long int]

將 Python 整數轉換為 C long int

k (int) [unsigned long]

將 Python 整數轉換為 C unsigned long,不進行溢位檢查。

L (int) [long long]

將 Python 整數轉換為 C long long

K (int) [unsigned long long]

將 Python 整數轉換為 C unsigned long long,不進行溢位檢查。

n (int) [Py_ssize_t]

將 Python 整數轉換為 C Py_ssize_t

c (bytesbytearray,長度為 1) [char]

將一個 Python 位元組(表示為長度為 1 的 bytesbytearray 物件)轉換為 C char

3.3 版本更改: 允許使用 bytearray 物件。

C (str,長度為 1) [int]

將一個 Python 字元(表示為長度為 1 的 str 物件)轉換為 C int

f (float) [float]

將 Python 浮點數轉換為 C float

d (float) [double]

將 Python 浮點數轉換為 C double

D (complex) [Py_complex]

將 Python 複數轉換為 C Py_complex 結構體。

其他物件

O (物件) [PyObject *]

將 Python 物件(不進行任何轉換)儲存在 C 物件指標中。因此,C 程式接收到傳遞的實際物件。不會建立對該物件新的強引用(即其引用計數不會增加)。儲存的指標不為 NULL

O! (物件) [typeobject, PyObject *]

將 Python 物件儲存在 C 物件指標中。這與 O 類似,但需要兩個 C 引數:第一個是 Python 型別物件的地址,第二個是儲存物件指標的 C 變數(型別為 PyObject*)的地址。如果 Python 物件不具有所需的型別,則會引發 TypeError

O& (物件) [converter, anything]

透過 converter 函式將 Python 物件轉換為 C 變數。這需要兩個引數:第一個是函式,第二個是 C 變數(任意型別)的地址,轉換為 void*converter 函式依次呼叫如下

status = converter(object, address);

其中 object 是要轉換的 Python 物件,address 是傳遞給 PyArg_Parse* 函式的 void* 引數。返回的 status 對於成功轉換應為 1,如果轉換失敗則為 0。當轉換失敗時,converter 函式應引發異常,並保持 address 的內容不變。

如果 converter 返回 Py_CLEANUP_SUPPORTED,則如果引數解析最終失敗,它可能會被第二次呼叫,從而使轉換器有機會釋放它已經分配的任何記憶體。在第二次呼叫中,object 引數將為 NULLaddress 將具有與原始呼叫相同的值。

3.1 版本更改: 添加了 Py_CLEANUP_SUPPORTED

p (bool) [int]

測試傳入值的真值(布林 **p**redicate),並將結果轉換為等效的 C 真/假整數值。如果表示式為真,則將 int 設定為 1,如果為假,則設定為 0。 這接受任何有效的 Python 值。有關 Python 如何測試值的真值,請參閱 真值測試

3.3 版本新增。

(items) (tuple) [matching-items]

該物件必須是 Python 序列,其長度是 items 中格式單元的數量。C 引數必須與 items 中的各個格式單元相對應。序列的格式單元可以是巢狀的。

可以傳遞 “long” 整數(其值超過平臺 LONG_MAX 的整數),但是不進行適當的範圍檢查——當接收欄位太小而無法接收該值時,最高有效位會被靜默截斷(實際上,語義是從 C 中的向下轉換繼承的——你的結果可能會有所不同)。

在格式字串中,其他幾個字元具有含義。這些字元可能不會出現在巢狀的括號內。它們是:

|

指示 Python 引數列表中剩餘的引數是可選的。與可選引數對應的 C 變數應初始化為它們的預設值——當未指定可選引數時,PyArg_ParseTuple() 不會觸及相應的 C 變數的內容。

$

PyArg_ParseTupleAndKeywords() 專用:指示 Python 引數列表中剩餘的引數是僅關鍵字的。目前,所有僅關鍵字的引數也必須是可選引數,因此在格式字串中,$ 之前必須始終指定 |

3.3 版本新增。

:

格式單元列表在此處結束;冒號後的字串用作錯誤訊息中的函式名稱(PyArg_ParseTuple() 引發的異常的 “關聯值”)。

;

格式單元列表在此處結束;分號後的字串用作錯誤訊息,*代替*預設錯誤訊息。:; 相互排斥。

請注意,提供給呼叫者的任何 Python 物件引用都是*借用*的引用;請不要釋放它們(即,不要減少它們的引用計數)!

傳遞給這些函式的附加引數必須是變數的地址,這些變數的型別由格式字串確定;它們用於儲存來自輸入元組的值。在上面格式單元列表中描述的少數情況下,這些引數用作輸入值;在這種情況下,它們應與相應格式單元指定的內容匹配。

為了成功轉換,arg 物件必須與格式匹配,並且格式必須耗盡。成功時,PyArg_Parse* 函式返回 true,否則返回 false 並引發適當的異常。當 PyArg_Parse* 函式由於某個格式單元的轉換失敗而失敗時,與該格式單元及其後續格式單元對應的地址處的變數將保持不變。

API 函式

int PyArg_ParseTuple(PyObject *args, const char *format, ...)
屬於 穩定 ABI 的一部分。

將僅接受位置引數的函式的引數解析為區域性變數。成功時返回 true;失敗時,返回 false 並引發適當的異常。

int PyArg_VaParse(PyObject *args, const char *format, va_list vargs)
屬於 穩定 ABI 的一部分。

PyArg_ParseTuple() 相同,但它接受 va_list 而不是可變數量的引數。

int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *const *keywords, ...)
屬於 穩定 ABI 的一部分。

將接受位置引數和關鍵字引數的函式的引數解析為區域性變數。keywords 引數是一個以 NULL 結尾的關鍵字引數名稱陣列,指定為以 null 結尾的 ASCII 或 UTF-8 編碼的 C 字串。空名稱表示僅限位置引數。成功時返回 true;失敗時,返回 false 並引發適當的異常。

注意

keywords 引數宣告在 C 中為 char *const*,在 C++ 中為 const char *const*。這可以使用 PY_CXX_CONST 宏覆蓋。

在 3.6 版本中更改: 添加了對僅限位置引數的支援。

在 3.13 版本中更改: keywords 引數現在在 C 中的型別為 char *const*,在 C++ 中的型別為 const char *const*,而不是 char**。添加了對非 ASCII 關鍵字引數名稱的支援。

int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *const *keywords, va_list vargs)
屬於 穩定 ABI 的一部分。

PyArg_ParseTupleAndKeywords() 相同,但它接受 va_list 而不是可變數量的引數。

int PyArg_ValidateKeywordArguments(PyObject*)
屬於 穩定 ABI 的一部分。

確保關鍵字引數字典中的鍵是字串。只有在不使用 PyArg_ParseTupleAndKeywords() 時才需要這樣做,因為後者已經執行此檢查。

在 3.2 版本中新增。

int PyArg_Parse(PyObject *args, const char *format, ...)
屬於 穩定 ABI 的一部分。

將接受單個位置引數的函式的引數解析為區域性變數。成功時返回 true;失敗時,返回 false 並引發適當的異常。

示例

// Function using METH_O calling convention
static PyObject*
my_function(PyObject *module, PyObject *arg)
{
    int value;
    if (!PyArg_Parse(arg, "i:my_function", &value)) {
        return NULL;
    }
    // ... use value ...
}
int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
屬於 穩定 ABI 的一部分。

一種更簡單的引數檢索形式,它不使用格式字串來指定引數的型別。使用此方法檢索其引數的函式應在函式或方法表中宣告為 METH_VARARGS。包含實際引數的元組應作為 args 傳遞;它實際上必須是一個元組。元組的長度必須至少為 min,且不超過 maxminmax 可以相等。必須將附加引數傳遞給函式,其中每個引數都應是指向 PyObject* 變數的指標;這些變數將用來自 args 的值填充;它們將包含借用引用。與 args 未給出的可選引數對應的變數將不會被填充;這些變數應由呼叫者初始化。此函式在成功時返回 true,如果 args 不是元組或包含錯誤數量的元素,則返回 false;如果出現故障,則會設定異常。

這是使用此函式的示例,取自弱引用的 _weakref 幫助模組的原始碼

static PyObject *
weakref_ref(PyObject *self, PyObject *args)
{
    PyObject *object;
    PyObject *callback = NULL;
    PyObject *result = NULL;

    if (PyArg_UnpackTuple(args, "ref", 1, 2, &object, &callback)) {
        result = PyWeakref_NewRef(object, callback);
    }
    return result;
}

在此示例中呼叫 PyArg_UnpackTuple() 完全等效於此呼叫 PyArg_ParseTuple()

PyArg_ParseTuple(args, "O|O:ref", &object, &callback)
PY_CXX_CONST

PyArg_ParseTupleAndKeywords()PyArg_VaParseTupleAndKeywords()keywords 引數宣告中,在 char *const* 前要插入的值(如果有)。C 語言預設為空,C++ 語言預設為 const (const char *const*)。要覆蓋此預設值,請在包含 Python.h 之前將其定義為所需的值。

3.13 版本中新增。

構建值

PyObject *Py_BuildValue(const char *format, ...)
返回值:新引用。屬於穩定 ABI 的一部分。

基於類似於 PyArg_Parse* 系列函式所接受的格式字串和一系列值建立一個新值。如果發生錯誤,則返回該值或 NULL;如果返回 NULL,則會引發異常。

Py_BuildValue() 並非總是構建一個元組。僅當其格式字串包含兩個或更多格式單元時,它才會構建一個元組。如果格式字串為空,則返回 None;如果它恰好包含一個格式單元,則返回該格式單元所描述的任何物件。要強制它返回大小為 0 或 1 的元組,請將格式字串用括號括起來。

當記憶體緩衝區作為引數傳遞以提供構建物件的資料時(例如對於 ss# 格式),會複製所需的資料。呼叫者提供的緩衝區永遠不會被 Py_BuildValue() 建立的物件引用。換句話說,如果您的程式碼呼叫 malloc() 並將分配的記憶體傳遞給 Py_BuildValue(),則您的程式碼負責在 Py_BuildValue() 返回後為該記憶體呼叫 free()

在以下描述中,帶引號的形式是格式單元;圓括號中的條目是格式單元將返回的 Python 物件型別;方括號中的條目是要傳遞的 C 值型別。

空格、製表符、冒號和逗號在格式字串中會被忽略(但在 s# 等格式單元內則不會)。這可以用來使長格式字串更具可讀性。

s ( strNone) [const char *]

使用 'utf-8' 編碼將以 null 結尾的 C 字串轉換為 Python str 物件。如果 C 字串指標為 NULL,則使用 None

s# ( strNone) [const char *, Py_ssize_t]

使用 'utf-8' 編碼將 C 字串及其長度轉換為 Python str 物件。如果 C 字串指標為 NULL,則忽略長度並返回 None

y ( bytes) [const char *]

這將 C 字串轉換為 Python bytes 物件。如果 C 字串指標為 NULL,則返回 None

y# ( bytes) [const char *, Py_ssize_t]

這將 C 字串及其長度轉換為 Python 物件。如果 C 字串指標為 NULL,則返回 None

z (strNone) [const char *]

s 相同。

z# ( strNone) [const char *, Py_ssize_t]

s# 相同。

u ( str) [const wchar_t *]

將以 null 結尾的 Unicode(UTF-16 或 UCS-4)資料的 wchar_t 緩衝區轉換為 Python Unicode 物件。如果 Unicode 緩衝區指標為 NULL,則返回 None

u# ( str) [const wchar_t *, Py_ssize_t]

將 Unicode(UTF-16 或 UCS-4)資料緩衝區及其長度轉換為 Python Unicode 物件。如果 Unicode 緩衝區指標為 NULL,則忽略長度並返回 None

U ( strNone) [const char *]

s 相同。

U# ( strNone) [const char *, Py_ssize_t]

s# 相同。

i (int) [int]

將普通 C int 轉換為 Python 整數物件。

b ( int) [char]

將普通 C char 轉換為 Python 整數物件。

h (int) [short int]

將普通 C short int 轉換為 Python 整數物件。

l (int) [long int]

將 C long int 轉換為 Python 整數物件。

B (int) [unsigned char]

將 C unsigned char 轉換為 Python 整數物件。

H (int) [unsigned short int]

將 C unsigned short int 轉換為 Python 整數物件。

I (int) [unsigned int]

將 C unsigned int 轉換為 Python 整數物件。

k (int) [unsigned long]

將 C unsigned long 轉換為 Python 整數物件。

L (int) [long long]

將 C long long 轉換為 Python 整數物件。

K (int) [unsigned long long]

將 C unsigned long long 轉換為 Python 整數物件。

n (int) [Py_ssize_t]

將 C Py_ssize_t 轉換為 Python 整數。

c (長度為 1 的 bytes) [char]

將表示位元組的 C int 轉換為長度為 1 的 Python bytes 物件。

C (str,長度為 1) [int]

將表示字元的 C int 轉換為長度為 1 的 Python str 物件。

d (float) [double]

將 C double 轉換為 Python 浮點數。

f (float) [float]

將 C float 轉換為 Python 浮點數。

D (complex) [Py_complex *]

將 C Py_complex 結構體轉換為 Python 複數。

O (物件) [PyObject *]

傳遞一個 Python 物件,不做任何修改,但建立一個新的強引用(即其引用計數加一)。如果傳入的物件是 NULL 指標,則假定這是因為產生該引數的呼叫發現了一個錯誤並設定了異常。因此,Py_BuildValue() 將返回 NULL 但不會引發異常。如果尚未引發任何異常,則會設定 SystemError

S (物件) [PyObject *]

O 相同。

N (物件) [PyObject *]

O 相同,但它不建立新的強引用。當物件是由引數列表中的物件建構函式的呼叫建立時,此項很有用。

O& (物件) [converter, anything]

透過 *轉換器* 函式將 *任何內容* 轉換為 Python 物件。該函式使用 *任何內容*(應與 void* 相容)作為其引數進行呼叫,並應返回一個“新”Python 物件,如果發生錯誤,則返回 NULL

(items) (tuple) [matching-items]

將一系列 C 值轉換為具有相同數量項的 Python 元組。

[items] (list) [匹配項]

將一系列 C 值轉換為具有相同數量項的 Python 列表。

{items} (dict) [匹配項]

將一系列 C 值轉換為 Python 字典。每對連續的 C 值都會向字典新增一項,分別作為鍵和值。

如果格式字串中存在錯誤,則會設定 SystemError 異常並返回 NULL

PyObject *Py_VaBuildValue(const char *format, va_list vargs)
返回值:新引用。屬於穩定 ABI 的一部分。

Py_BuildValue() 相同,只不過它接受 va_list 而不是可變數量的引數。