解析参数和构建值

这些函数在创建您自己的扩展函数和方法时很有用。更多信息和示例可在 扩展和嵌入 Python 解释器 中找到。

这三个函数中前三个,PyArg_ParseTuple()PyArg_ParseTupleAndKeywords()PyArg_Parse(),都使用格式字符串来告诉函数预期参数。这些函数的格式字符串使用相同的语法。

解析参数

格式字符串由零个或多个“格式单元”组成。一个格式单元描述一个 Python 对象;它通常是一个单个字符或一个带括号的格式单元序列。除了少数例外,一个不是带括号的序列的格式单元通常对应于这些函数的一个单地址参数。在以下描述中,引号形式是格式单元;(圆括号)中的条目是与格式单元匹配的 Python 对象类型;[方括号]中的条目是应传递其地址的 C 变量类型。

字符串和缓冲区

这些格式允许将对象访问为连续的内存块。您不必为返回的 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,但也包括一些只读对象,例如 memoryviewbytes

    除了这个 bf_releasebuffer 要求之外,没有检查来验证输入对象是否不可变(例如,它是否会响应对可写缓冲区的请求,或者另一个线程是否可以修改数据)。

注意

对于所有格式的 # 变体(s#y# 等),宏 PY_SSIZE_T_CLEAN 必须在包含 Python.h 之前定义。在 Python 3.9 及更早版本中,如果定义了 PY_SSIZE_T_CLEAN 宏,长度参数的类型为 Py_ssize_t,否则为 int。

s (str) [const char *]

将 Unicode 对象转换为指向字符字符串的 C 指针。指向现有字符串的指针存储在您传递地址的字符指针变量中。C 字符串以 NUL 结尾。Python 字符串不能包含嵌入的空代码点;如果包含,则会引发 ValueError 异常。Unicode 对象使用 'utf-8' 编码转换为 C 字符串。如果此转换失败,则会引发 UnicodeError

注意

此格式不接受 字节类对象。如果您想接受文件系统路径并将它们转换为 C 字符串,最好使用 O& 格式,并将 PyUnicode_FSConverter() 作为 converter

在版本 3.5 中更改: 以前,当在 Python 字符串中遇到嵌入的空代码点时,会引发 TypeError

s* (str字节类对象) [Py_buffer]

此格式接受 Unicode 对象以及字节类对象。它填充调用者提供的 Py_buffer 结构。在这种情况下,生成的 C 字符串可能包含嵌入的空字节。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,在这种情况下,buf 成员 Py_buffer 结构将设置为 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 对象,不尝试任何转换。如果对象不是字节对象,则会引发 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 编码为字符缓冲区。它仅适用于不包含嵌入式空字节的编码数据。

此格式需要两个参数。第一个参数仅用作输入,必须是 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 格式不同,此变体允许包含空字符的输入数据。

它需要三个参数。第一个参数仅用作输入,必须是 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 版本中变更: u, u#, Z, 和 Z# 被移除,因为它们使用了遗留的 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 (object) [PyObject *]

将 Python 对象(不进行任何转换)存储在 C 对象指针中。因此,C 程序接收传递的实际对象。不会创建对该对象的新的 强引用(即,它的引用计数不会增加)。存储的指针不为 NULL

O! (object) [typeobject, PyObject *]

将 Python 对象存储到 C 对象指针中。这类似于 O,但接受两个 C 参数:第一个是 Python 类型对象的地址,第二个是 C 变量的地址(类型为 PyObject*),对象指针将存储到其中。如果 Python 对象没有所需的类型,则会引发 TypeError

O& (对象) [转换器, 任何]

通过转换器函数将 Python 对象转换为 C 变量。这接受两个参数:第一个是函数,第二个是 C 变量的地址(任意类型),转换为 void*转换器函数依次按如下方式调用

status = converter(object, address);

其中对象是要转换的 Python 对象,地址是传递给 PyArg_Parse* 函数的 void* 参数。返回的状态对于成功转换应为 1,对于转换失败应为 0。当转换失败时,转换器函数应该引发异常并保持地址的内容不变。

如果转换器返回 Py_CLEANUP_SUPPORTED,如果参数解析最终失败,它可能会被再次调用,从而使转换器有机会释放它已经分配的任何内存。在这个第二次调用中,对象参数将为 NULL地址将与原始调用中的值相同。

在版本 3.1 中更改: Py_CLEANUP_SUPPORTED 已添加。

p (bool) [int]

测试传入的值是否为真(布尔predicate)并将结果转换为等效的 C 真/假整数值。如果表达式为真,则将 int 设置为 1,如果表达式为假,则设置为 0。这接受任何有效的 Python 值。有关 Python 如何测试值是否为真的更多信息,请参见 真值测试

在版本 3.3 中添加。

(items) (tuple) [匹配项]

对象必须是 Python 序列,其长度与中的格式单元数量相同。C 参数必须与中的各个格式单元相对应。序列的格式单元可以嵌套。

可以传递“长”整数(其值超过平台的 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 *keywords[], ...)
稳定 ABI 的一部分。

将接受位置参数和关键字参数的函数的参数解析到局部变量中。keywords 参数是一个以 NULL 结尾的关键字参数名称数组。空名称表示 仅位置参数。成功返回 True;失败返回 False 并引发相应的异常。

版本 3.6 中的变更: 添加了对 仅位置参数 的支持。

int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *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 的一部分。

用于解构“旧式”函数的参数列表的函数——这些函数使用 METH_OLDARGS 参数解析方法,该方法已在 Python 3 中删除。不建议在新的代码中使用此方法进行参数解析,并且标准解释器中的大多数代码已被修改为不再为此目的使用此方法。但是,它仍然是分解其他元组的便捷方法,并且可以继续为此目的使用。

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 未给出的可选参数的变量将不会被填充;这些应由调用者初始化。如果 args 不是元组或包含错误数量的元素,则此函数返回 true,否则返回 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)

构建值

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 结尾的 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 (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 (bytes 长度为 1) [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 (object) [PyObject *]

传递一个 Python 对象而不修改,但创建一个新的 强引用 到它(即它的引用计数增加 1)。如果传递的 object 是一个 NULL 指针,则假定这是因为生成参数的调用发现了错误并设置了异常。因此,Py_BuildValue() 将返回 NULL 但不会引发异常。如果还没有引发异常,则会设置 SystemError

S (对象) [PyObject *]

O 相同。

N (对象) [PyObject *]

O 相同,但它不会创建新的 强引用。当对象由参数列表中对对象构造函数的调用创建时,这很有用。

O& (对象) [转换器, 任何]

通过转换器函数将任何内容转换为 Python 对象。该函数以任何内容(应与 void* 兼容)作为参数调用,并应返回一个“新” Python 对象,如果发生错误则返回 NULL

(items) (tuple) [匹配项]

将 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 而不是可变数量的参数。