代码之家  ›  专栏  ›  技术社区  ›  Evandro Coan

如何修复使用PythonC扩展时的“UnicodeDecodeError:'utf-8'编解码器无法解码字节”?

  •  0
  • Evandro Coan  · 技术社区  · 7 年前

    bug.txt :

    event "øat" not handled
    

    我在该文件上编写了以下Python C扩展 fastfilewrapper.cpp

    #include <Python.h>
    #include <cstdio>
    #include <iostream>
    #include <sstream>
    #include <fstream>
    
    static PyObject* hello_world(PyObject *self, PyObject *args) {
        printf("Hello, world!\n");
        std::string retval;
        std::ifstream fileifstream;
    
        fileifstream.open("./bug.txt");
        std::getline( fileifstream, retval );
        fileifstream.close();
        std::cout << "retval " << retval << std::endl;
        return Py_BuildValue( "s", retval.c_str() );
    }
    
    static PyMethodDef hello_methods[] = { {
            "hello_world", hello_world, METH_NOARGS,
            "Print 'hello world' from a method defined in a C extension."
        },
        {NULL, NULL, 0, NULL}
    };
    
    static struct PyModuleDef hello_definition = {
        PyModuleDef_HEAD_INIT,
        "hello", "A Python module that prints 'hello world' from C code.",
        -1, hello_methods
    };
    
    PyMODINIT_FUNC PyInit_fastfilepackage(void) {
        Py_Initialize();
        return PyModule_Create(&hello_definition);
    }
    

    我用它做的 pip3 install . setup.py

    from distutils.core import setup, Extension
    
    # https://bugs.python.org/issue35893
    from distutils.command import build_ext
    
    def get_export_symbols(self, ext):
        parts = ext.name.split(".")
        if parts[-1] == "__init__":
            initfunc_name = "PyInit_" + parts[-2]
        else:
            initfunc_name = "PyInit_" + parts[-1]
    
    build_ext.build_ext.get_export_symbols = get_export_symbols
    
    setup(name='fastfilepackage', version='1.0',  \
          ext_modules=[Extension('fastfilepackage', ['fastfilewrapper.cpp'])])
    

    然后,我用这个 test.py

    import fastfilepackage
    
    iterable = fastfilepackage.hello_world()
    print('iterable', iterable)
    

    但是当我运行 Python脚本:

    $ PYTHONIOENCODING=utf8 python3 test.py
    Hello, world!
    retval event "▒at" not handled
    Traceback (most recent call last):
      File "test.py", line 3, in <module>
        iterable = fastfilepackage.hello_world()
    UnicodeDecodeError: 'utf-8' codec can't decode byte 0xf8 in position 7: invalid start byte
    

    i、 例如,在绑定C和Python时忽略这些错误。

    file_in = open( './bug.txt', errors='replace' )
    line = file_in.read()
    print( "The input line was: {line}".format(line=line) )
    

    这相当于什么 errors='replace' 当绑定到 Python C Extensions

    0 回复  |  直到 7 年前
        1
  •  1
  •   Stephan Schlecht    7 年前

    return PyUnicode_DecodeUTF8(retval.c_str(), retval.size(), "replace");
    

    在我们的情况下,这将给出如下结果:

    Hello, world!
    retval event "?at" not handled
    iterable event "�at" not handled