解析参数和构建值

这些函数在创建自己的扩展Function和方法时很有用。 扩展和嵌入 Python 解释器中提供了其他信息和示例。

所描述的这些函数的前三个PyArg_ParseTuple()PyArg_ParseTupleAndKeywords()PyArg_Parse()都使用* format 字符串*,用于将预期参数告知Function。格式字符串对每个函数使用相同的语法。

Parsing arguments

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

字符串和缓冲区

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

通常,当格式将指针设置为缓冲区时,缓冲区由相应的 Python 对象 Management,并且缓冲区共享此对象的生存期。您不必自己释放任何 Memory。唯一的 exception 是eses#etet#

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

除非另有说明,否则缓冲区不是 NUL 终止的。

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

Note

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

  • s(str)[const char *]

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

Note

此格式不接受bytes-like objects。如果要接受文件系统路径并将其转换为 C 字符串,则最好将O&格式与PyUnicode_FSConverter()用作* converter *。

在版本 3.5 中进行了更改:以前,在 Python 字符串中遇到嵌入式空代码点时,引发了TypeError

  • s*(strbytes-like object)[Py_buffer]

    • 此格式接受 Unicode 对象以及类似字节的对象。它填充了调用者提供的Py_buffer结构。在这种情况下,生成的 C 字符串可能包含嵌入的 NUL 字节。 Unicode 对象使用'utf-8'编码转换为 C 字符串。
  • s#(str,只读bytes-like object)[const char *,int 或+67+]

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

    • 类似于s,但是 Python 对象也可以是None,在这种情况下,C 指针设置为NULL
  • z*(strbytes-like objectNone)[Py_buffer]

    • s*一样,但是 Python 对象也可以是None,在这种情况下,Py_buffer结构的buf成员设置为NULL
  • z#(str,只读bytes-like objectNone)[const char *,int 或+95+]

    • 类似于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 或+113+]

    • s#上的此变体不接受 Unicode 对象,仅接受类似字节的对象。
  • S(bytes)[PyBytesObject *]

    • 要求 Python 对象是bytes对象,且不try任何转换。如果对象不是字节对象,则引发TypeError。 C 变量也可以语句为PyObject*
  • Y(bytearray)[PyByteArrayObject *]

  • u(str)[const Py_UNICODE *]

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

在版本 3.5 中进行了更改:以前,在 Python 字符串中遇到嵌入式空代码点时,引发了TypeError

从版本 3.3 开始不推荐使用,将在版本 4.0 中删除:老式Py_UNICODE API 的一部分;请迁移到使用PyUnicode_AsWideCharString()

  • u#(str)[const Py_UNICODE *,int 或+153+]

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

从版本 3.3 开始不推荐使用,将在版本 4.0 中删除:老式Py_UNICODE API 的一部分;请迁移到使用PyUnicode_AsWideCharString()

  • Z(strNone)[const Py_UNICODE *]

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

从版本 3.3 开始不推荐使用,将在版本 4.0 中删除:老式Py_UNICODE API 的一部分;请迁移到使用PyUnicode_AsWideCharString()

  • Z#(strNone)[const Py_UNICODE *,int 或+176+]

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

从版本 3.3 开始不推荐使用,将在版本 4.0 中删除:老式Py_UNICODE API 的一部分;请迁移到使用PyUnicode_AsWideCharString()

  • U(str)[PyObject *]

    • 要求 Python 对象是 Unicode 对象,而无需try任何转换。如果对象不是 Unicode 对象,则引发TypeError。 C 变量也可以语句为PyObject*
  • w*(读写bytes-like object)[Py_buffer]

    • 该格式接受任何实现读写缓冲区接口的对象。它填充了调用者提供的Py_buffer结构。缓冲区可能包含嵌入的空字节。缓冲区完成后,调用方必须调用PyBuffer_Release()
  • es(str)[const char * encoding,char ** buffer]

    • s上的此变体用于将 Unicode 编码到字符缓冲区中。它仅适用于没有嵌入 NUL 字节的编码数据。

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

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

  • et(strbytesbytearray)[const char * encoding,char ** buffer]

    • es相同,不同之处在于字节字符串对象无需重新编码即可直接传递。相反,该实现假定字节字符串对象使用传入的编码作为参数。
  • es#(str)[const char * encoding,char ** buffer,int 或+223+ * buffer_length]

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

它需要三个参数。第一个仅用作 Importing,并且必须是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#(strbytesbytearray)[const char * encoding,char ** buffer,int or +245+ * buffer_length]

    • es#相同,不同之处在于字节字符串对象无需重新编码即可直接传递。相反,该实现假定字节字符串对象使用传入的编码作为参数。

Numbers

  • b(int)[未签名的字符]

    • 将非负的 Python 整数转换为存储在 C unsigned char中的无符号微小 int。
  • B(int)[未签名的字符]

    • 将 Python 整数转换为微小的 int 而不进行溢出检查,存储在 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)[未签名长]

    • 将 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(长度为 1 的bytesbytearray)[char]

    • 将表示为长度为 1 的bytesbytearray对象的 Python 字节转换为 C char

在版本 3.3 中更改:允许bytearray个对象。

  • C(长度为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结构。

Other objects

  • O(对象)[PyObject *]

    • 将 Python 对象(不进行任何转换)存储在 C 对象指针中。因此,C 程序将接收传递的实际对象。对象的引用计数不会增加。存储的指针不是NULL
  • O!(对象)[* typeobject *,PyObject *]

    • 将 Python 对象存储在 C 对象指针中。这类似于O,但是有两个 C 参数:第一个是 Python 类型对象的地址,第二个是对象指针存储在其中的 C 变量(类型PyObject*)的地址。如果 Python 对象没有必需的类型,则引发TypeError
  • O&(对象)[转换器任何内容]

    • pass* converter *函数将 Python 对象转换为 C 变量。这有两个参数:第一个是函数,第二个是转换为void *的 C 变量(任意类型)的地址。 * converter *函数依次调用如下:
status = converter(object, address);

其中* object 是要转换的 Python 对象, address 是传递给PyArg_Parse*()函数的void*参数。对于成功的转换,返回的 status 应该为1,如果转换失败则为0。当转换失败时, converter 函数应引发一个异常,并使 address *的内容保持不变。

如果* converter 返回Py_CLEANUP_SUPPORTED,则如果参数解析finally失败,它可能会被第二次调用,从而使转换器有机会释放其已分配的任何内存。在第二个调用中, object *参数将为NULL地址将具有与原始呼叫相同的值。

在版本 3.1 中进行了更改:添加了Py_CLEANUP_SUPPORTED

  • p(bool)[int]

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

版本 3.3 中的新Function。

  • (items)(tuple)[匹配项]

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

可以传递“长”整数(其值超过平台的LONG_MAX的整数),但是不会进行适当的范围检查-当接收字段太小而无法接收该值时,最高有效位会被静默截断(实际上,语义是继承自 C 语言的垂头丧气-您的行驶里程可能会有所不同)。

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

  • |

    • 指示 Python 参数列表中的其余参数是可选的。与可选参数相对应的 C 变量应初始化为其默认值-如果未指定可选参数,则PyArg_ParseTuple()不会触及相应 C 变量的内容。
  • $

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

版本 3.3 中的新Function。

  • :

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

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

请注意,提供给调用方的任何 Python 对象引用都是“借用”引用;不要减少其参考计数!

传递给这些函数的其他参数必须是类型由格式字符串确定的变量的地址;这些用于存储来自 ImportingTuples 的值。如上述格式单位列表中所述,在某些情况下,这些参数将用作 Importing 值。在这种情况下,它们应与为相应格式单位指定的内容匹配。

为了使转换成功,* arg *对象必须与格式匹配,并且格式必须用尽。成功时,PyArg_Parse*()函数返回 true,否则返回 false 并引发适当的异常。当PyArg_Parse*()函数由于其中一种格式单位的转换失败而失败时,与该格式单位和以下格式单位对应的地址处的变量将保持不变。

API Functions

  • int PyArg_ParseTuple(PyObject *args ,const char format *,...)

    • 解析仅将位置参数转换为局部变量的函数的参数。成功返回 true;失败时,它返回 false 并引发适当的异常。
  • int PyArg_VaParse(PyObject *args ,const char format *,va_list * vargs *)

  • int PyArg_ParseTupleAndKeywords(PyObject *args PyObject kw *,const char *format ,char keywords [] *,...)

    • 解析将位置参数和关键字参数都转换为局部变量的函数的参数。 * keywords *参数是关键字参数名称的NULL终止数组。空名称表示positional-only parameters。成功返回 true;失败时,它返回 false 并引发适当的异常。

在版本 3.6 中更改:添加了对positional-only parameters的支持。

  • int PyArg_VaParseTupleAndKeywords(PyObject *args PyObject kw *,const char *format ,char keywords [] *,va_list * vargs *)

  • int PyArg_ValidateKeywordArguments(PyObject ***)

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

3.2 版中的新Function。

  • int PyArg_Parse(PyObject *args ,const char format *,...)

    • 用于解构“旧式”函数的参数列表的函数-这些是使用METH_OLDARGS参数解析方法的函数,该函数已在 Python 3 中删除。建议不要在新代码和大多数代码中将其用于参数解析。标准解释器中的修改为不再用于此目的。但是,它仍然是分解其他 Tuples 的便捷方法,并且可以 continue 用于该目的。
  • int PyArg_UnpackTuple(PyObject *args ,const char name *,Py_ssize_t * min *,Py_ssize_t * max *,...)

    • 参数检索的一种更简单形式,它不使用格式字符串来指定参数的类型。使用此方法检索其参数的函数应在函数或方法表中语句为METH_VARARGS。包含实际参数的 Tuples 应作为* args 传递;它实际上必须是一个 Tuples。Tuples 的长度必须至少为 min 且不大于 max *; * min max 可能相等。必须将其他参数传递给函数,每个参数都应是指向PyObject*变量的指针;这些将由 args 的值填充;它们将包含借用的参考。对应于 args 没有给出的可选参数的变量将不会被填写;这些应该由调用方初始化。成功时此函数返回 true,如果 args *不是 Tuples 或包含错误数量的元素,则返回 false。如果发生故障,将设置一个 exception。

这是使用此Function的一个示例,该示例取自_weakref helper 模块的来源,以获取弱引用:

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)

Building values

  • PyObject * Py_BuildValue(const char ** format *,...)
    • 返回值:新参考.

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

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

当将内存缓冲区作为参数传递以提供数据以生成对象时,就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 *,int 或+455+]

      • 使用'utf-8'编码将 C 字符串及其长度转换为 Python str对象。如果 C 字符串指针是NULL,则忽略长度,并返回None
    • y(bytes)[const char *]

      • 这会将 C 字符串转换为 Python bytes对象。如果 C 字符串指针为NULL,则返回None
    • y#(bytes)[const char *,int 或+471+]

      • 这会将 C 字符串及其长度转换为 Python 对象。如果 C 字符串指针为NULL,则返回None
    • z(strNone)[const char *]

      • s相同。
    • z#(strNone)[const char *,int 或+483+]

      • s#相同。
    • u(str)[const wchar_t *]

      • 将以 NULL 终止的 Unicode(UTF-16 或 UCS-4)数据的wchar_t缓冲区转换为 Python Unicode 对象。如果 Unicode 缓冲区指针为NULL,则返回None
    • u#(str)[const wchar_t *,int 或+494+]

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

      • s相同。
    • U#(strNone)[const char *,int 或+506+]

      • s#相同。
    • i(int)[int]

      • 将普通 C int转换为 Python 整数对象。
    • b(int)[字符]

      • 将普通 C char转换为 Python 整数对象。
    • h(int)[short 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)[unsigned int]

      • 将 C unsigned int转换为 Python 整数对象。
    • k(int)[未签名长]

      • 将 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的字符)[字符]

      • 将代表字节的 C int转换为长度为 1 的 Python bytes对象。
    • C(长度为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(对象)[PyObject *]

      • 传递一个不变的 Python 对象(除了引用计数,该计数增加一)。如果传入的对象是NULL指针,则认为这是由于产生该参数的调用发现错误并设置异常而引起的。因此,Py_BuildValue()将返回NULL,但不会引发异常。如果尚未引发任何异常,则设置SystemError
    • S(对象)[PyObject *]

      • O相同。
    • N(对象)[PyObject *]

      • O相同,不同之处在于它不会增加对象的引用计数。当pass调用参数列表中的对象构造函数创建对象时很有用。
    • O&(对象)[转换器任何内容]

      • pass* converter 函数将 anything 转换为 Python 对象。该函数以 anything *(应与void *兼容)作为参数调用,并应返回“新” Python 对象,如果发生错误则返回NULL
    • (items)(tuple)[匹配项]

      • 将具有相同数量项的 C 值序列转换为 PythonTuples。
    • [items](list)[匹配项]

      • 将 C 值序列转换为具有相同数量项的 Python 列表。
    • {items}(dict)[匹配项]

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

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

  • PyObject * Py_VaBuildValue(const char ** format *,va_list * vargs *)
    • 返回值:新参考.

Py_BuildValue()相同,除了它接受 va_list 而不是可变数量的参数。