解析参数和构建值¶
这些函数在创建自己的扩展函数和方法时非常有用。更多信息和示例请参见扩展和嵌入 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()
。es
、es#
、et
和et#
格式会分配结果缓冲区。在处理完数据(或在任何提前中止的情况下)之后,您必须调用PyMem_Free()
。其他格式接受
str
或只读的bytes-like object,例如bytes
,并提供指向其缓冲区的const char *
指针。在这种情况下,缓冲区是“借用”的:它由相应的 Python 对象管理,并与该对象的生命周期共享。您无需自行释放任何内存。为了确保底层缓冲区可以安全借用,对象的
PyBufferProcs.bf_releasebuffer
字段必须为NULL
。这会阻止常见的可变对象,如bytearray
,但也会阻止一些只读对象,如bytes
的memoryview
。除了这个
bf_releasebuffer
要求之外,没有检查来验证输入对象是否是不可变的(例如,它是否会接受可写缓冲区的请求,或者另一个线程是否可以改变数据)。
s
(str
) [const char *]将 Unicode 对象转换为指向字符字符串的 C 指针。指向现有字符串的指针存储在您传递地址的字符指针变量中。C 字符串以 NUL 终止。Python 字符串不得包含嵌入的 null 代码点;如果包含,将引发
ValueError
异常。Unicode 对象使用'utf-8'
编码转换为 C 字符串。如果此转换失败,将引发UnicodeError
。备注
此格式不接受bytes-like objects。如果您想接受文件系统路径并将其转换为 C 字符字符串,最好使用
O&
格式,并以PyUnicode_FSConverter()
作为转换器。3.5 版本中的变化: 以前,当 Python 字符串中遇到嵌入的 null 代码点时,会引发
TypeError
。s*
(str
或 类字节对象) [Py_buffer]此格式接受 Unicode 对象和类字节对象。它填充调用者提供的
Py_buffer
结构。在这种情况下,生成的 C 字符串可能包含嵌入的 NUL 字节。Unicode 对象使用'utf-8'
编码转换为 C 字符串。s#
(str
, 只读 bytes-like object) [const char *,Py_ssize_t
]类似于
s*
,但它提供一个借用缓冲区。结果存储在两个 C 变量中,第一个是指向 C 字符串的指针,第二个是其长度。字符串可能包含嵌入的 null 字节。Unicode 对象使用'utf-8'
编码转换为 C 字符串。z
(str
或None
) [const char *]与
s
类似,但 Python 对象也可以是None
,在这种情况下,C 指针被设置为NULL
。z*
(str
, bytes-like object 或None
) [Py_buffer]类似于
s*
,但 Python 对象也可以是None
,在这种情况下,Py_buffer
结构的buf
成员被设置为NULL
。z#
(str
, 只读 bytes-like object 或None
) [const char *,Py_ssize_t
]类似于
s#
,但 Python 对象也可以是None
,在这种情况下,C 指针被设置为NULL
。y
(只读 bytes-like object) [const char *]此格式将类字节对象转换为指向借用字符字符串的 C 指针;它不接受 Unicode 对象。字节缓冲区不得包含嵌入的空字节;如果包含,则引发
ValueError
异常。3.5 版本中的变化: 以前,当字节缓冲区中遇到嵌入的空字节时,会引发
TypeError
。y*
(类字节对象) [Py_buffer]此
s*
变体不接受 Unicode 对象,只接受类字节对象。这是接受二进制数据的推荐方式。y#
(只读 bytes-like object) [const char *,Py_ssize_t
]此
s#
变体不接受 Unicode 对象,只接受类字节对象。S
(bytes
) [PyBytesObject *]要求 Python 对象是一个
bytes
对象,不尝试任何转换。如果对象不是字节对象,则引发TypeError
。C 变量也可以声明为PyObject*。Y
(bytearray
) [PyByteArrayObject *]要求 Python 对象是一个
bytearray
对象,不尝试任何转换。如果对象不是bytearray
对象,则引发TypeError
。C 变量也可以声明为PyObject*。U
(str
) [PyObject *]要求 Python 对象是 Unicode 对象,不尝试任何转换。如果对象不是 Unicode 对象,则引发
TypeError
。C 变量也可以声明为 PyObject*。w*
(可读写 bytes-like object) [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
,bytes
或bytearray
) [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
,bytes
或bytearray
) [const char *encoding, char **buffer,Py_ssize_t
*buffer_length]与
es#
相同,只是字节字符串对象会直接传递,无需重新编码。相反,实现假定字节字符串对象使用作为参数传递的编码。
3.12 版本中的变化: u
, u#
, Z
, 和 Z#
已被移除,因为它们使用了旧版的 Py_UNICODE*
表示。
数字¶
这些格式允许将 Python 数字或单个字符表示为 C 数字。需要int
、float
或complex
的格式也可以使用相应的特殊方法__index__()
、__float__()
或__complex__()
将 Python 对象转换为所需类型。
对于带符号整数格式,如果值超出 C 类型的范围,则会引发OverflowError
。对于无符号整数格式,不进行范围检查——当接收字段太小无法接收值时,最高位会被悄悄截断。
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,不进行溢出检查。
3.14 版本中的变化: 如果可用,使用
__index__()
。L
(int
) [long long]将 Python 整数转换为 C long long。
K
(int
) [unsigned long long]将 Python 整数转换为 C unsigned long long,不进行溢出检查。
3.14 版本中的变化: 如果可用,使用
__index__()
。n
(int
) [Py_ssize_t
]将 Python 整数转换为 C
Py_ssize_t
。c
(bytes
或 长度为 1 的bytearray
) [char]将表示为长度为 1 的
bytes
或bytearray
对象的 Python 字节转换为 C char。3.3 版本中的变化: 允许
bytearray
对象。C
(长度为 1 的str
) [int]将表示为长度为 1 的
str
对象的 Python 字符转换为 C int。f
(float
) [float]将 Python 浮点数转换为 C float。
d
(float
) [double]将 Python 浮点数转换为 C double。
D
(complex
) [Py_complex]将 Python 复数转换为 C
Py_complex
结构体。
其他对象¶
O
(object) [PyObject *]将 Python 对象(不进行任何转换)存储在 C 对象指针中。因此,C 程序接收到实际传递的对象。不会创建新的强引用(即不会增加其引用计数)。存储的指针不是
NULL
。O!
(object) [typeobject, PyObject *]将 Python 对象存储在 C 对象指针中。这类似于
O
,但它需要两个 C 参数:第一个是 Python 类型对象的地址,第二个是 C 变量(类型为PyObject*)的地址,对象指针将存储在此变量中。如果 Python 对象不具有所需类型,则引发TypeError
。
O&
(object) [converter, address]通过转换器函数将 Python 对象转换为 C 变量。这需要两个参数:第一个是函数,第二个是 C 变量(任意类型)的地址,转换为void*。转换器函数反过来按如下方式调用
status = converter(object, address);
其中 object 是要转换的 Python 对象,address 是传递给
PyArg_Parse*
函数的 void* 参数。返回的 status 应为1
表示成功转换,0
表示转换失败。当转换失败时,converter 函数应引发异常并保持 address 的内容不变。如果转换器返回
Py_CLEANUP_SUPPORTED
,那么如果参数解析最终失败,它可能会被第二次调用,从而给转换器一个机会释放它已经分配的任何内存。在第二次调用中,object参数将为NULL
;address将与原始调用中的值相同。转换器示例:
PyUnicode_FSConverter()
和PyUnicode_FSDecoder()
。3.1 版本中的变化: 添加了
Py_CLEANUP_SUPPORTED
。p
(bool
) [int]测试传入值的真值(布尔predicate),并将结果转换为其等效的 C 真/假整数值。如果表达式为真,将 int 设置为
1
;如果为假,则设置为0
。这接受任何有效的 Python 值。有关 Python 如何测试值的真值的更多信息,请参阅真值测试。在 3.3 版本加入。
(items)
(sequence) [matching-items]该对象必须是 Python 序列(
str
、bytes
或bytearray
除外),其长度为 items 中格式单元的数量。C 参数必须与 items 中的各个格式单元对应。序列的格式单元可以嵌套。如果items包含存储借用缓冲区(
s
,s#
,z
,z#
,y
, 或y#
)或借用引用(S
,Y
,U
,O
, 或O!
)的格式单元,则该对象必须是 Python 元组。items中O&
格式单元的转换器不得存储借用缓冲区或借用引用。3.14 版本开始不推荐: 如果items包含存储借用缓冲区或借用引用的格式单元,则非元组序列已被弃用。
其他一些字符在格式字符串中具有意义。它们不能出现在嵌套括号内。它们是:
|
表示 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 终止的 ASCII 或 UTF-8 编码的 C 字符串形式的关键字参数名称的
NULL
终止数组。空名称表示仅位置参数。成功时返回 true;失败时返回 false 并引发相应的异常。备注
在 C 中,keywords 参数声明为 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且不超过max;min和max可以相等。必须向函数传递额外的参数,每个参数都应该是指向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*之前的R值。对于 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 的元组,请将格式字符串括起来。当内存缓冲区作为参数传递以提供数据来构建对象时,例如对于
s
和s#
格式,所需数据会被复制。调用者提供的缓冲区绝不会被Py_BuildValue()
创建的对象引用。换句话说,如果您的代码调用malloc()
并将分配的内存传递给Py_BuildValue()
,那么一旦Py_BuildValue()
返回,您的代码就有责任为该内存调用free()
。在以下描述中,带引号的形式是格式单元;(圆括号)中的条目是格式单元将返回的 Python 对象类型;[方括号]中的条目是要传递的 C 值类型。
格式字符串中会忽略空格、制表符、冒号和逗号(但在
s#
等格式单元内则不会)。这可以用于使长格式字符串更易读。s
(str
或None
) [const char *]使用
'utf-8'
编码将以 null 结尾的 C 字符串转换为 Pythonstr
对象。如果 C 字符串指针为NULL
,则使用None
。s#
(str
或None
) [const char *,Py_ssize_t
]使用
'utf-8'
编码将 C 字符串及其长度转换为 Pythonstr
对象。如果 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
(str
或None
) [const char *]与
s
相同。z#
(str
或None
) [const char *,Py_ssize_t
]与
s#
相同。u
(str
) [const wchar_t *]将以 null 结尾的
wchar_t
Unicode(UTF-16 或 UCS-4)数据缓冲区转换为 Python Unicode 对象。如果 Unicode 缓冲区指针为NULL
,则返回None
。u#
(str
) [const wchar_t *,Py_ssize_t
]将 Unicode (UTF-16 或 UCS-4) 数据缓冲区及其长度转换为 Python Unicode 对象。如果 Unicode 缓冲区指针为
NULL
,则忽略长度并返回None
。U
(str
或None
) [const char *]与
s
相同。U#
(str
或None
) [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 整数。p
(bool
) [int]将 C int 转换为 Python
bool
对象。请注意,此格式需要一个
int
参数。与 C 语言中的大多数其他上下文不同,可变参数不会自动强制转换为合适的类型。您可以使用(x) ? 1 : 0
或!!x
将其他类型(例如,指针或浮点数)转换为合适的int
值。在 3.14 版本加入。
c
(长度为 1 的bytes
)[char]将表示字节的 C int 转换为长度为 1 的 Python
bytes
对象。C
(长度为 1 的str
) [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
(object) [PyObject *]不加修改地传递 Python 对象,但创建对它的新强引用(即其引用计数增加一)。如果传入的对象是
NULL
指针,则假定这是因为生成参数的调用发现错误并设置了异常。因此,Py_BuildValue()
将返回NULL
但不会引发异常。如果尚未引发异常,则设置SystemError
。S
(object) [PyObject *]与
O
相同。N
(object) [PyObject *]与
O
相同,不同之处在于它不创建新的强引用。当对象由参数列表中对对象构造函数的调用创建时很有用。O&
(object) [converter, anything]通过 converter 函数将 anything 转换为 Python 对象。该函数以 anything(应与 void* 兼容)作为其参数进行调用,并应返回一个新的 Python 对象,如果发生错误则返回
NULL
。(items)
(tuple
) [matching-items]将一系列 C 值转换为具有相同项目数的 Python 元组。
[items]
(list
) [matching-items]将一系列 C 值转换为具有相同项目数的 Python 列表。
{items}
(dict
) [matching-items]将一系列 C 值转换为 Python 字典。每对连续的 C 值向字典添加一个项目,分别作为键和值。
如果格式字符串中存在错误,则设置
SystemError
异常并返回NULL
。
-
PyObject *Py_VaBuildValue(const char *format, va_list vargs)¶
- 返回值: 新引用。 稳定ABI 的一部分。
与
Py_BuildValue()
相同,不同之处在于它接受va_list
而不是可变数量的参数。