解析参数和构建值 — Python 文档

来自菜鸟教程
Python/docs/3.9/c-api/arg
跳转至:导航、​搜索

解析参数和构建值

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

描述的这些函数中的前三个,PyArg_ParseTuple()PyArg_ParseTupleAndKeywords()PyArg_Parse(),都使用 格式字符串]用于告诉函数有关预期参数的信息。 格式字符串对这些函数中的每一个都使用相同的语法。

解析参数

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

字符串和缓冲区

这些格式允许将对象作为连续的内存块进行访问。 您不必为返回的 unicode 或字节区域提供原始存储。

一般来说,当一种格式设置一个指向缓冲区的指针时,缓冲区由相应的 Python 对象管理,缓冲区共享此对象的生命周期。 您不必自己释放任何内存。 唯一的例外是 eses#etet#

但是,当 Py_buffer 结构被填满时,底层缓冲区被锁定,以便调用者随后可以在 Py_BEGIN_ALLOW_THREADS 块内使用该缓冲区,而不会有可变数据被调整大小或破坏的风险. 因此, 在完成数据处理后(或在任何早期中止情况下),您必须调用 PyBuffer_Release()

除非另有说明,否则缓冲区不是以 NUL 结尾的。

一些格式需要一个只读的 bytes-like object,并设置一个指针而不是一个缓冲区结构。 它们通过检查对象的 PyBufferProcs.bf_releasebuffer 字段是否为 NULL 来工作,这不允许诸如 bytearray 之类的可变对象。

笔记

对于所有 # 格式变体(s#y# 等),长度参数的类型(int 或 Py_ssize_t)通过定义包含 Python.h 之前的宏 PY_SSIZE_T_CLEAN。 如果定义了宏,则长度为 Py_ssize_t 而不是 int。 此行为将在未来的 Python 版本中更改为仅支持 Py_ssize_t 并放弃 int 支持。 最好始终定义 PY_SSIZE_T_CLEAN


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 or bytes-like object) [Py_buffer]

此格式接受 Unicode 对象以及类似字节的对象。 它填充了调用者提供的 Py_buffer 结构。 在这种情况下,生成的 C 字符串可能包含嵌入的 NUL 字节。 Unicode 对象使用 'utf-8' 编码转换为 C 字符串。

s# (str, 只读 bytes-like object) [const char *, int or Py_ssize_t]

s* 类似,不同之处在于它不接受可变对象。 结果存储在两个 C 变量中,第一个是指向 C 字符串的指针,第二个是它的长度。 该字符串可能包含嵌入的空字节。 Unicode 对象使用 'utf-8' 编码转换为 C 字符串。

z (strNone) [const char *]

s类似,但Python对象也可能是None,在这种情况下C指针设置为NULL

z* (str, bytes-like object or None) [Py_buffer]

s*,但Python对象也可能是None,在这种情况下,Py_buffer结构的buf成员被设置为[ X146X]。

z# (str, 只读 bytes-like object or None) [const char *, int or Py_ssize_t]

s#类似,但Python对象也可能是None,在这种情况下C指针设置为NULL

y(只读 bytes-like object)[const char *]

这种格式将类字节对象转换为指向字符串的 C 指针; 它不接受 Unicode 对象。 字节缓冲区不能包含嵌入的空字节; 如果是,则会引发 ValueError 异常。

3.5 版更改: 以前,当在字节缓冲区中遇到嵌入的空字节时,会引发 TypeError

y* (bytes-like object) [Py_buffer]

s* 上的这个变体不接受 Unicode 对象,只接受类似字节的对象。 这是推荐的接受二进制数据的方式。

y#(只读 bytes-like object)[const char *, int or Py_ssize_t]

s# 上的这个变体不接受 Unicode 对象,只接受类似字节的对象。

S (bytes) [PyBytesObject *]

要求 Python 对象是 bytes 对象,而不尝试任何转换。 如果对象不是字节对象,则引发 TypeError。 C 变量也可以声明为 PyObject*

Y (bytearray) [PyByteArrayObject *]

要求 Python 对象是 bytearray 对象,不尝试任何转换。 如果对象不是 bytearray 对象,则引发 TypeError。 C 变量也可以声明为 PyObject*

u (str) [const Py_UNICODE *]

将 Python Unicode 对象转换为指向以 NUL 结尾的 Unicode 字符缓冲区的 C 指针。 您必须传递 Py_UNICODE 指针变量的地址,该变量将填充指向现有 Unicode 缓冲区的指针。 请注意 Py_UNICODE 字符的宽度取决于编译选项(它是 16 位或 32 位)。 Python 字符串不得包含嵌入的空代码点; 如果是,则会引发 ValueError 异常。

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

u# (str) [const Py_UNICODE *, int 或 Py_ssize_t]

u 上的这个变体存储到两个 C 变量中,第一个是指向 Unicode 数据缓冲区的指针,第二个是它的长度。 此变体允许空代码点。

Z (strNone) [const Py_UNICODE *]

u类似,但Python对象也可能是None,在这种情况下,Py_UNICODE指针被设置为NULL

Z# (strNone) [const Py_UNICODE *, int 或 Py_ssize_t]

u#类似,但Python对象也可能是None,在这种情况下,Py_UNICODE指针被设置为NULL

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 字节的编码数据。

这种格式需要两个参数。 第一个仅用作输入,并且必须是 const char*,它指向作为 NUL 终止字符串的编码名称,或 NULL,在这种情况下为 'utf-8' 编码。 如果 Python 不知道命名编码,则会引发异常。 第二个参数必须是 char**; 它引用的指针的值将被设置为一个包含参数文本内容的缓冲区。 文本将以第一个参数指定的编码进行编码。

PyArg_ParseTuple() 将分配所需大小的缓冲区,将编码数据复制到该缓冲区中并调整 *buffer 以引用新分配的存储。 调用者负责在使用后调用 PyMem_Free() 来释放分配的缓冲区。

et (str, bytes or bytearray) [const char *encoding, char **buffer]

es 相同,除了字节字符串对象在不重新编码的情况下被传递。 相反,该实现假定字节字符串对象使用作为参数传入的编码。

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

s# 上的这个变体用于将 Unicode 编码到字符缓冲区中。 与 es 格式不同,此变体允许包含 NUL 字符的输入数据。

它需要三个参数。 第一个仅用作输入,并且必须是 const char*,它指向作为 NUL 终止字符串的编码名称,或 NULL,在这种情况下为 'utf-8' 编码。 如果 Python 不知道命名编码,则会引发异常。 第二个参数必须是 char**; 它引用的指针的值将被设置为一个包含参数文本内容的缓冲区。 文本将以第一个参数指定的编码进行编码。 第三个参数必须是一个整数指针; 引用的整数将设置为输出缓冲区中的字节数。

有两种操作模式:

如果 *buffer 指向一个 NULL 指针,该函数将分配一个所需大小的缓冲区,将编码数据复制到该缓冲区中并设置 *buffer 以引用新分配的存储空间。 调用者负责调用 PyMem_Free() 以在使用后释放分配的缓冲区。

如果 *buffer 指向一个非 NULL 指针(一个已经分配的缓冲区),PyArg_ParseTuple() 将使用这个位置作为缓冲区并解释初始值*buffer_length 作为缓冲区大小。 然后它将编码的数据复制到缓冲区中并以 NUL 终止它。 如果缓冲区不够大,则会设置 ValueError

在这两种情况下,*buffer_length 被设置为没有尾随 NUL 字节的编码数据的长度。

et# (str, bytes or bytearray) [const char *encoding, char **buffer, int or Py_ssize_t *缓冲区长度]

es# 相同,除了字节字符串对象在不重新编码的情况下被传递。 相反,该实现假定字节字符串对象使用作为参数传入的编码。


数字

b (int) [无符号字符]

将非负 Python 整数转换为无符号小整数,存储在 C unsigned char 中。

B (int) [无符号字符]

将 Python 整数转换为没有溢出检查的小整数,存储在 C unsigned char 中。

h (int) [短整数]

将 Python 整数转换为 C short int

H (int) [unsigned short int]

将 Python 整数转换为 C unsigned short int,不进行溢出检查。

i (int) [int]

将 Python 整数转换为普通的 C int

I (int) [无符号整数]

将 Python 整数转换为 C unsigned int,不进行溢出检查。

l (int) [long int]

将 Python 整数转换为 C long int

k (int) [unsigned long]

将 Python 整数转换为 C unsigned long 而不进行溢出检查。

L (int) [长长]

将 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 (bytes or bytearray of length 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) [双]

将 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 函数将 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]

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

3.3 版中的新功能。

(items) (元组) [匹配项]

该对象必须是一个 Python 序列,其长度是 items 中格式单元的数量。 C 参数必须对应于 items 中的各个格式单位。 序列的格式单元可以嵌套。

可以传递“长”整数(值超过平台 LONG_MAX 的整数),但是没有进行适当的范围检查——当接收字段太小而无法接收值时,最高有效位被静默截断(实际上,语义是从 C 中的向下转换继承而来的——你的里程可能会有所不同)。

其他一些字符在格式字符串中具有含义。 这些可能不会出现在嵌套括号内。 他们是:

|

指示 Python 参数列表中的其余参数是可选的。 对应于可选参数的 C 变量应初始化为其默认值——当未指定可选参数时,PyArg_ParseTuple() 不会触及相应 C 变量的内容。

$

PyArg_ParseTupleAndKeywords() only:表示 Python 参数列表中的剩余参数是仅关键字的。 目前,所有仅关键字参数也必须是可选参数,因此必须始终在格式字符串中的 $ 之前指定 |

3.3 版中的新功能。

:

格式单位列表到此结束; 冒号后的字符串用作错误消息中的函数名称(PyArg_ParseTuple() 引发的异常的“关联值”)。

;

格式单位列表到此结束; 分号后的字符串用作错误消息 而不是默认错误消息的:; 相互排斥。

请注意,提供给调用者的任何 Python 对象引用都是 借用的 引用; 不要减少它们的引用计数!

传递给这些函数的附加参数必须是其类型由格式字符串确定的变量的地址; 这些用于存储来自输入元组的值。 有几种情况,如上面的格式单位列表中所述,这些参数被用作输入值; 在这种情况下,它们应该与为相应格式单元指定的内容相匹配。

要使转换成功,arg 对象必须与格式匹配并且格式必须已用完。 成功时, PyArg_Parse* 函数返回 true,否则返回 false 并引发适当的异常。 当 PyArg_Parse* 函数因格式单元之一的转换失败而失败时,与该格式单元对应的地址处的变量以及以下格式单元保持不变。


API 函数

int PyArg_ParseTuple(PyObject *args, const char *format, ...)
解析仅将位置参数转换为局部变量的函数的参数。 成功返回真; 失败时,它返回 false 并引发适当的异常。
int PyArg_VaParse(PyObject *args, const char *format, va_list vargs)
PyArg_ParseTuple() 相同,除了它接受 va_list 而不是可变数量的参数。
int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...)

解析将位置和关键字参数都带入局部变量的函数的参数。 keywords 参数是一个以 NULL 结尾的关键字参数名称数组。 空名称表示 仅位置参数 。 成功返回真; 失败时,它返回 false 并引发适当的异常。

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

int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], va_list vargs)
PyArg_ParseTupleAndKeywords() 相同,除了它接受 va_list 而不是可变数量的参数。
int PyArg_ValidateKeywordArguments(PyObject*)

确保关键字参数字典中的键是字符串。 仅在未使用 PyArg_ParseTupleAndKeywords() 时才需要,因为后者已经进行了此检查。

3.2 版中的新功能。

int PyArg_Parse(PyObject *args, const char *format, ...)
用于解构“旧式”函数的参数列表的函数——这些函数使用 METH_OLDARGS 参数解析方法,该方法已在 Python 3 中删除。 这不推荐用于新代码中的参数解析,并且标准解释器中的大多数代码已被修改为不再为此目的使用它。 然而,它仍然是分解其他元组的便捷方式,并且可能会继续用于该目的。
int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)

一种更简单的参数检索形式,它不使用格式字符串来指定参数的类型。 使用此方法检索其参数的函数应在函数或方法表中声明为 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, ...)

基于类似于 PyArg_Parse* 系列函数和值序列接受的格式字符串创建新值。 出错时返回值或NULL; 如果返回 NULL,则会引发异常。

Py_BuildValue() 并不总是构建一个元组。 仅当其格式字符串包含两个或多个格式单元时,它才会构建元组。 如果格式字符串为空,则返回None; 如果它只包含一个格式单元,则返回该格式单元所描述的任何对象。 要强制它返回大小为 0 或 1 的元组,请将格式字符串括起来。

当内存缓冲区作为参数传递以向构建对象提供数据时,对于 ss# 格式,将复制所需的数据。 调用者提供的缓冲区永远不会被 Py_BuildValue() 创建的对象引用。 换句话说,如果您的代码调用 malloc() 并将分配的内存传递给 Py_BuildValue(),您的代码负责为该内存调用一次 free() Py_BuildValue () 返回。

以下说明中,引用形式为格式单位; (圆)括号中的条目是格式单元将返回的 Python 对象类型; [方]括号中的条目是要传递的C值的类型。

字符空格、制表符、冒号和逗号在格式字符串中被忽略(但不在 s# 等格式单位内)。 这可用于使长格式字符串更具可读性。

s (strNone) [const char *]

使用 'utf-8' 编码将空终止的 C 字符串转换为 Python str 对象。 如果 C 字符串指针是 NULL,则使用 None

s# (str or None) [const char *, int or 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 *, int or Py_ssize_t]

这会将 C 字符串及其长度转换为 Python 对象。 如果 C 字符串指针为 NULL,则返回 None

z (strNone) [const char *]

s 相同。

z# (str or None) [const char *, int or Py_ssize_t]

s# 相同。

u (str) [const wchar_t *]

将 Unicode(UTF-16 或 UCS-4)数据的以空字符结尾的 wchar_t 缓冲区转换为 Python Unicode 对象。 如果 Unicode 缓冲区指针为 NULL,则返回 None

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

将 Unicode(UTF-16 或 UCS-4)数据缓冲区及其长度转换为 Python Unicode 对象。 如果 Unicode 缓冲区指针为 NULL,则忽略长度并返回 None

U (strNone) [const char *]

s 相同。

U# (str or None) [const char *, int or Py_ssize_t]

s# 相同。

i (int) [int]

将普通 C int 转换为 Python 整数对象。

b (int) [字符]

将普通的 C char 转换为 Python 整数对象。

h (int) [短整数]

将普通的 C short int 转换为 Python 整数对象。

l (int) [long int]

将 C long int 转换为 Python 整数对象。

B (int) [无符号字符]

将 C unsigned char 转换为 Python 整数对象。

H (int) [unsigned short int]

将 C unsigned short int 转换为 Python 整数对象。

I (int) [无符号整数]

将 C unsigned int 转换为 Python 整数对象。

k (int) [unsigned long]

将 C unsigned long 转换为 Python 整数对象。

L (int) [长长]

将 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 of length 1) [char]

将表示一个字节的 C int 转换为长度为 1 的 Python bytes 对象。

C (str 长度为 1) [int]

将表示字符的 C int 转换为长度为 1 的 Python str 对象。

d (float) [双]

将 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 对象。 该函数使用 anything(应该与 void* 兼容)作为其参数调用,并且应该返回一个“新”Python 对象,如果出现错误,则返回 NULL发生了。

(items) (元组) [匹配项]

将 C 值序列转换为具有相同项数的 Python 元组。

[items] (list) [匹配项]

将 C 值序列转换为具有相同项数的 Python 列表。

{items} (dict) [匹配项]

将 C 值序列转换为 Python 字典。 每对连续的 C 值向字典添加一个项目,分别作为键和值。

如果格式字符串有错误,则设置 SystemError 异常并返回 NULL

PyObject *Py_VaBuildValue(const char *format, va_list vargs)
Py_BuildValue() 相同,除了它接受 va_list 而不是可变数量的参数。