如果字符串中有非ASCII字符,如何将C字符串(char数组)转换为Python字符串?

我在C程序中嵌入了一个Python解释器。 假设C程序从文件中读取一些字节到char数组,并且(以某种方式)学习字节表示具有特定编码的文本(例如,ISO 8859-1,Windows-1252或UTF-8)。 如何将此char数组的内容解码为Python字符串?

Python字符串通常应该是unicode类型 – 例如,Windows-1252编码输入中的0x93变为u'\u0201c'

我试图使用PyString_Decode ,但是当字符串中有非ASCII字符时它总是会失败。 这是一个失败的例子:

 #include  #include  int main(int argc, char *argv[]) { char c_string[] = { (char)0x93, 0 }; PyObject *py_string; Py_Initialize(); py_string = PyString_Decode(c_string, 1, "windows_1252", "replace"); if (!py_string) { PyErr_Print(); return 1; } return 0; } 

错误消息是UnicodeEncodeError: 'ascii' codec can't encode character u'\u201c' in position 0: ordinal not in range(128) ,这表示即使我们在调用PyString_Decode指定了windows_1252 ,也会使用ascii编码。

下面的代码通过使用PyString_FromString创建未解码的字节的Python字符串,然后调用其decode方法来解决此问题:

 #include  #include  int main(int argc, char *argv[]) { char c_string[] = { (char)0x93, 0 }; PyObject *raw, *decoded; Py_Initialize(); raw = PyString_FromString(c_string); printf("Undecoded: "); PyObject_Print(raw, stdout, 0); printf("\n"); decoded = PyObject_CallMethod(raw, "decode", "s", "windows_1252"); Py_DECREF(raw); printf("Decoded: "); PyObject_Print(decoded, stdout, 0); printf("\n"); return 0; } 

PyString_Decode执行此操作:

 PyObject *PyString_Decode(const char *s, Py_ssize_t size, const char *encoding, const char *errors) { PyObject *v, *str; str = PyString_FromStringAndSize(s, size); if (str == NULL) return NULL; v = PyString_AsDecodedString(str, encoding, errors); Py_DECREF(str); return v; } 

IOW,它基本上完成了你在第二个例子中所做的事情 – 转换为字符串,然后解码字符串。 这里的问题来自PyString_AsDecodedString,而不是PyString_AsDecodedObject。 PyString_AsDecodedString执行PyString_AsDecodedObject,但随后尝试将生成的unicode对象转换为具有默认编码的字符串对象(对于您来说,看起来就像是ASCII)。 那就是失败的地方。

我相信你需要做两次调用 – 但你可以使用PyString_AsDecodedObject而不是调用python“decode”方法。 就像是:

 #include  #include  int main(int argc, char *argv[]) { char c_string[] = { (char)0x93, 0 }; PyObject *py_string, *py_unicode; Py_Initialize(); py_string = PyString_FromStringAndSize(c_string, 1); if (!py_string) { PyErr_Print(); return 1; } py_unicode = PyString_AsDecodedObject(py_string, "windows_1252", "replace"); Py_DECREF(py_string); return 0; } 

我不完全确定PyString_Decode这种方式背后的原因是什么。 python-dev上的一个非常古老的线程似乎表明它与链接输出有关,但由于Python方法没有做同样的事情,我不确定它是否仍然相关。

您不希望将字符串解码为Unicode表示forms,您只想将其视为字节数组,对吗?

只需使用PyString_FromString

 char *cstring; PyObject *pystring = PyString_FromString(cstring); 

就这样。 现在你有了一个Python str()对象。 请参阅此处的文档: https : //docs.python.org/2/c-api/string.html

关于如何指定“str”或“unicode”,我有点困惑。 如果您有非ASCII字符,它们会完全不同。 如果你想解码一个C字符串并且你确切知道它所在的字符集,那么是的, PyString_DecodeString是一个很好的起点。

尝试在“ if (!py_string) ”子句中调用PyErr_Print() 。 也许pythonexception会给你一些更多的信息。