Python 3.12 C-API 中删除了一堆与 unicode 相关的功能。对我来说不幸的是,我们的库中有一段非常旧的代码(~2010)使用这些代码,我需要以某种方式将此功能迁移到 3.12,因为我们希望最终升级到 3.12。我特别纠结的一件事是删除
u#
参数。以下代码将解析传递给 foo
的任何位置参数(包括 unicode 字符串),并将它们存储在 input
中:
static PyObject *
foo(PyObject *self, PyObject *args) {
Py_UNICODE *input;
Py_ssize_t length;
if (!PyArg_ParseTuple(args, "u#", &input, &length)) {
return NULL;
}
...
}
但是,根据 docs,
u#
已被删除:
在版本 3.12 中进行了更改:删除了
、u
、u#
和Z
,因为它们使用了旧版 Py_UNICODE* 表示形式。Z#
当在纯 python 中编译和使用当前代码时,只会抛出类似
bad-format-character
的内容。
Py_UNICODE
只是 wchar_t
所以很容易修复。但是随着 u#
的删除,我不确定如何让 PyArg_ParseTuple
接受 unicode 输入参数。使用 s#
代替 u#
不起作用,因为它不能处理任何宽字符。如何在 Python 3.12 中迁移此调用?
s#
可以很好地处理 Unicode,但它为您提供 UTF-8 而不是 wchar_t
。如果您特别需要 wchar 表示形式,可以使用 PyUnicode_AsWideCharString
: 从字符串对象中获取一个 wchar 表示形式
Py_ssize_t size;
wchar_t *wchar_representation = PyUnicode_AsWideCharString(stringobj, &size);
if (!wchar_representation) {
// error occurred. do something about that.
}
// do stuff with wchar_representation, then once you're done,
PyMem_Free(wchar_representation);
与旧的
Py_UNICODE
API 不同,这会分配一个新的缓冲区,当您使用完它后,您必须使用 PyMem_Free
释放它。