2016-12-21 10 views
1

私は最近、Python 3.4.3からPython 3.5.2にPythonを埋め込んだC++プロジェクトをアップグレードしました(これは32または64ビットとしてビルドされます)両方のバージョンで同じ動作をします)。 Pythonコードによって呼び出されるいくつかのC++のコードでそれを引き上げその後C/C++ Python例外のトレースバックが生成されていません

static PyObject* MyException_type_obj = 0; 

void setup(PyObject* module){ 
    MyException_type_obj = PyErr_NewException("my_module.MyException", NULL, NULL); 

    PyObject* dict = PyModule_GetDict(module); 
    PyDict_SetItemString(dict, "MyException", MyException_type_obj); 
} 

私は自分の例外を作成してい

static PyObject* RaiseIt(PyObject* self, PyObject* args) 
{ 
    PyErr_Format(Forever_Exception_type_obj, "Exit Requested"); 
    return 0; 
} 

これまでのところ、とても良いです。私がPythonでそれを捕まえれば、すべてが問題ありません。

try: 
    my_module.raise_it() 
except my_module.MyException: 
    import sys, traceback 
    exc_type, exc_value, exc_tb = sys.exc_info() 
    print(traceback.format_exception(exc_type, exc_value, exc_tb) 

正しいtracbackをコマンドラインに表示します。しかし

、私はPyErr_Fetchを使用するC++/Pythonで同じようなことをやろう:

std::string get_traceback(){ 
    PyObject* type; 
    PyObject* value; 
    PyObject* traceback; 

    PyErr_Fetch(&type, &value, &traceback); 

    std::string fcn = ""; 
    fcn += "def get_pretty_traceback(exc_type, exc_value, exc_tb):\n"; 
    fcn += " import sys, traceback\n"; 
    fcn += " lines = []\n"; 
    fcn += " lines = traceback.format_exception(exc_type, exc_value, exc_tb)\n"; 
    fcn += " output = '\\n'.join(lines)\n"; 
    fcn += " return output\n"; 

    PyRun_SimpleString(fcn.c_str()); 
    PyObject* mod = PyImport_ImportModule("__main__"); 
    PyObject* method = PyObject_GetAttrString(mod, "get_pretty_traceback"); 
    PyObject* outStr = PyObject_CallObject(method, Py_BuildValue("OOO", type, value, traceback)); 
    std::string pretty = PyBytes_AsString(PyUnicode_AsASCIIString(outStr)); 

    Py_DECREF(method); 
    Py_DECREF(outStr); 

    return pretty; 
} 

それが故障し、私がnull outStrを取得します。これはどちらか(マイナー文字列に関連した変化で)のpython 2.7で発生しません、余談として

'str' object has no attribute '__cause__' 

取得いくつかの追加の詳細

fcn += " lines = []\n"; 
    fcn += " try:\n"; 
    fcn += "  lines = traceback.format_exception(exc_type, exc_value, exc_tb)\n"; 
    fcn += " except Exception as e:\n"; 
    fcn += "  print('Exception while rendering a python exception for C')\n"; 
    fcn += "  print(e)\n"; 
    fcn += " output = '\\n'.join(lines)\n"; 

は私に不可解なエラーメッセージを表示します。それはPython 3.5で私にとって唯一のものです。

この同じC++のget_traceback()関数は、Pythonで開始された例外(C++の例外ではない)で正常に動作します。

答えて

2

私のPyErr_Fetch呼び出しの直後に、PyErr_NormalizeExceptionが必要です。これは、値を文字列から例外オブジェクトのインスタンスに変換します。

PyObject* type; 
PyObject* value; 
PyObject* traceback; 

PyErr_Fetch(&type, &value, &traceback); 
PyErr_NormalizeException(&type, &value, &traceback); // Added line 

... 

問題を修正します。私はC++で生成された例外とPythonで生成された例外から来る値が値を変更する理由を知りませんが、これが処理します。

関連する問題