LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 166|回复: 0

解析参数并构建值变量

[复制链接]
发表于 2024-1-24 17:33:04 | 显示全部楼层 |阅读模式


在创建你自己的扩展函数和方法时,这些函数是有用的。其它的信息和样例见 扩展和嵌入 Python 解释器 。

这些函数描述的前三个,PyArg_ParseTuple(),PyArg_ParseTupleAndKeywords(),以及 PyArg_Parse(),它们都使用 格式化字符串 来将函数期待的参数告知函数。这些函数都使用相同语法规则的格式化字符串。

解析参数
一个格式化字符串包含 0 或者更多的格式单元。一个格式单元用来描述一个 Python 对象;它通常是一个字符或者由括号括起来的格式单元序列。除了少数例外,一个非括号序列的格式单元通常对应这些函数的具有单一地址的参数。在接下来的描述中,双引号内的表达式是格式单元;圆括号 () 内的是对应这个格式单元的 Python 对象类型;方括号 [] 内的是传递的 C 变量(变量集)类型。

字符串和缓存区
这些格式允许将对象按照连续的内存块形式进行访问。你没必要提供返回的 unicode 字符或者字节区的原始数据存储。

除非另有说明,缓冲区是不会以空终止的。

有三种办法可以将字符串和缓冲区转换到 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#、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 字符串是已空结束的。Python 字符串不能包含嵌入的无效的代码点;如果由,一个 ValueError 异常会被引发。Unicode 对象被转化成 'utf-8' 编码的 C 字符串。如果转换失败,一个 UnicodeError 异常被引发。

备注 这个表达式不接受 bytes-like objects。如果你想接受文件系统路径并将它们转化成 C 字符串,建议使用 O& 表达式配合 PyUnicode_FSConverter() 作为 转化函数。
在 3.5 版本发生变更: 以前,当 Python 字符串中遇到了嵌入的 null 代码点会引发 TypeError 。

s* (str or bytes-like object) [Py_buffer]
这个表达式既接受 Unicode 对象也接受类字节类型对象。它为由调用者提供的 Py_buffer 结构赋值。这里结果的 C 字符串可能包含嵌入的 NUL 字节。Unicode 对象通过 'utf-8' 编码转化成 C 字符串。

s# (str, read-only bytes-like object) [const char *, Py_ssize_t]
像是 s*,区别在于它提供了一个 借入的缓冲区。 结果存储在两个 C 变量中,第一个是指向 C 字符串的指针,第二个是其长度。 该字符串可能包含嵌入的空字节。 Unicode 对象会使用 'utf-8' 编码格式转换为 C 字符串。

z (str or None) [const char *]
与 s 类似,但 Python 对象也可能为 None,在这种情况下,C 指针设置为 NULL。

z* (str, bytes-like object or None) [Py_buffer]
与 s* 类似,但 Python 对象也可能为 None,在这种情况下,Py_buffer 结构的 buf 成员设置为 NULL。

z# (str, read-only bytes-like object 或者 None) [const char *, Py_ssize_t]
与 s# 类似,但 Python 对象也可能为 None,在这种情况下,C 指针设置为 NULL。

y (read-only bytes-like object) [const char *]
这个格式会将一个类字节对象转换为一个指向 借入的 字符串的 C 指针;它不接受 Unicode 对象。 字节缓冲区不可包含嵌入的空字节;如果包含这样的内容,将会引发 ValueError 异常。exception is raised.

在 3.5 版本发生变更: 以前,当字节缓冲区中遇到了嵌入的 null 字节会引发 TypeError 。

y* (bytes-like object) [Py_buffer]
s* 的变式,不接受 Unicode 对象,只接受类字节类型变量。这是接受二进制数据的推荐方法。

y# (read-only bytes-like object) [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* (可读写 bytes-like object) [Py_buffer]
这个表达式接受任何实现可读写缓存区接口的对象。它为调用者提供的 Py_buffer 结构赋值。缓冲区可能存在嵌入的 null 字节。当缓冲区使用完后调用者需要调用 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, 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 的初始值解释为缓冲区大小。 然后,它将将编码的数据复制到缓冲区,并终止它。 如果缓冲区不够大,将设置一个 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* 表示形式。

数字
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:C:expr:'unsigned long-long',而不进行溢出检查。

n (int) [Py_ssize_t]
将一个 Python 整型转化成一个 C Py_ssize_t Python 元大小类型。

c (bytes 或者 bytearray 长度为 1) [char]
将一个 Python 字节类型,如一个长度为 1 的 bytes 或 bytearray 对象,转换为 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 Python 复数类型。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表