Python 3.12 C-API移除了u#格式字符,如何处理?
在Python 3.12的C-API中,很多与unicode相关的功能被删除了。对我来说,这很麻烦,因为我们库里有一段很老的代码(大约2010年)使用了这些功能,而我们计划最终升级到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;
}
...
}
但是,根据文档,u#
已经被删除了:
在3.12版本中更改:
u
、u#
、Z
和Z#
被移除,因为它们使用了过时的Py_UNICODE*表示法。
而且当前的代码在编译并在纯Python中使用时,会抛出类似bad-format-character
的错误。
Py_UNICODE
其实就是wchar_t
,这部分问题比较好解决。但是由于u#
被去掉了,我不确定该如何让PyArg_ParseTuple
接受unicode输入参数。用s#
代替u#
也不行,因为它无法处理宽字符。那么,我该如何在Python 3.12中迁移这个调用呢?
1 个回答
1
s#
可以很好地处理Unicode字符,但它给你的是UTF-8格式,而不是 wchar_t
。如果你特别需要PyUnicode_AsWideCharString
:
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
接口不同,这个方法会分配一个新的内存空间,使用完后你需要用 PyMem_Free
来释放这块内存。