Python 3.12 C-API移除了u#格式字符,如何处理?

0 投票
1 回答
23 浏览
提问于 2025-04-14 18:13

在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版本中更改:uu#ZZ#被移除,因为它们使用了过时的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 来释放这块内存。

撰写回答