문자열에 비 ASCII 문자가있을 때 C 문자열 (char 배열)을 Python 문자열로 변환하는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/213628

문제

C 프로그램에 Python 통역사를 포함 시켰습니다. C 프로그램이 파일에서 일부 바이트를 숯 배열로 읽고 바이트가 특정 인코딩 (예 : ISO 8859-1, Windows-1252 또는 UTF-8)이있는 텍스트를 나타냅니다. 이 char 어레이의 내용을 파이썬 문자열로 어떻게 디코딩합니까?

파이썬 문자열은 일반적으로 유형이어야합니다 unicode- 예를 들어, a 0x93 Windows-1252에서 인코딩 된 입력은 a가됩니다 u'\u0201c'.

나는 사용하려고 시도했다 PyString_Decode, 그러나 문자열에 비 ASCII 문자가있을 때 항상 실패합니다. 다음은 실패한 예입니다.

#include <Python.h>
#include <stdio.h>

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 명확하지 않은 바이트의 파이썬 문자열을 만들려면 decode 방법:

#include <Python.h>
#include <stdio.h>

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_asdecodedobject보다는 pystring_asdecodedstring에서 발생합니다. pystring_asdecodedstring pystring_asdecodedobject를 수행하지만 결과 유니 코드 객체를 기본 인코딩을 사용하여 문자열 객체로 변환하려고합니다 (ASCII처럼 보입니다). 그것이 실패하는 곳입니다.

두 번의 호출을해야한다고 생각하지만 Python "Decode"메소드를 호출하지 않고 pystring_asdecodedobject를 사용할 수 있습니다. 같은 것 :

#include <Python.h>
#include <stdio.h>

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의 아주 오래된 실 출력을 체인하는 것과 관련이 있음을 나타내는 것처럼 보이지만 파이썬 방법이 동일하지 않기 때문에 여전히 관련이 있는지 확실하지 않습니다.

다른 팁

문자열을 유니 코드 표현으로 디코딩하고 싶지 않습니다. 바이트 배열로 취급하고 싶습니까?

그냥 사용하십시오 PyString_FromString:

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

그게 다야. 이제 파이썬이 있습니다 str() 물체. 여기서 문서를 참조하십시오. https://docs.python.org/2/c-api/string.html

나는 "str"또는 "unicode"를 지정하는 방법에 대해 약간 혼란스러워합니다. ASCII가 아닌 문자가 있으면 상당히 다릅니다. C 문자열을 디코딩하려는 경우 그리고 당신은 어떤 캐릭터를 설정하는지 정확히 알고 있습니다. 그렇습니다. PyString_DecodeString 시작하기에 좋은 곳입니다.

전화 해보세요 PyErr_Print() ""에서 "if (!py_string)"조항. 아마도 Python 예외는 더 많은 정보를 제공 할 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top