当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如果字符串中有非ASCII字符,如何将C字符串(char数组)转换为Python字符串?》经验,为你挑选了1个好方法。

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

Python字符串通常应该是类型unicode- 例如,0x93Windows-1252编码的输入变为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),表示ascii即使我们windows_1252在调用中指定,也使用编码PyString_Decode.

以下代码通过使用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;
}

Tony Meyer.. 6

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的方法不这样做,我不知道如果这仍然具有现实意义.



1> Tony Meyer..:

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的方法不这样做,我不知道如果这仍然具有现实意义.

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有