8

アプリケーションに Python インタープリターを組み込みました。PyRun_String()APIを使用してPythonスクリプトを実行するために使用します。PyErr_Fetch()エラー/例外が発生した場合を使用して、エラー情報を取得できます。これにより、例外タイプ、例外値、および例外トレースバックが得られます。次に、トレースバックから発生したエラーの行番号を見つけます。ただし、構文エラーの場合、トレースバックは一切得られません。トレースバックなしで行番号を取得する方法を知っている人はいますか..? 例外タイプまたは例外値を使用して取得する方法はありますか..?

Python のドキュメントには、次のように記載されています。

このクラスのインスタンスには、詳細に簡単にアクセスできるように、属性 filename、lineno、offset、および text があります。例外インスタンスの str() は、メッセージのみを返します。

埋め込み python で SyntaxError のファイル名と lineno 属性を取得するにはどうすればよいですか?

どんな助けでも大歓迎です。前もって感謝します。


ブレットさん、ご提案ありがとうございます。しかし、私はすでに PyObject_GetAttr() を使用して試しました。

テスト目的で使用した以下のサンプル コードを参照してください。

int main(int argc, char** argv)
{
    Py_Initialize();

    // Get a reference to the main module.
    PyObject* main_module =
        PyImport_AddModule("__main__");

    // Get the main module's dictionary
    // and make a copy of it.
    PyObject* main_dict =
        PyModule_GetDict(main_module);

    const char *script_source = "def main():\n\tprint('Hello'\n\nmain()";

    PyObject *res = PyRun_String(script_source,Py_file_input,main_dict,main_dict);
    if(res == NULL)
    {
        PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;
        PyErr_Fetch(&ptype,&pvalue,&ptraceback);

        PyObject* py_filename = PyUnicode_FromString("filename");
        PyObject* file_name = PyObject_GetAttr(ptype,py_filename);

        PyObject* py_lineno = PyUnicode_FromString("lineno");
        PyObject* line_no = PyObject_GetAttr(ptype,py_lineno);
    }
}

script_source に意図的に構文エラーを挿入しました。

file_name および line_no オブジェクトから実際のファイル名と行番号を取得できません。

file_name および line_no オブジェクトをデバッグしようとしましたが、内容は次のようになります。「構文エラー オブジェクトのメンバー ファイル名」および「構文エラー オブジェクトのメンバー lineno」

これらのオブジェクトは呼び出し可能ではないため、これらに対して PyObject_Call() バリアントを使用することはできません。

これらのオブジェクトから実際のファイル名と行番号を取得する方法はありますか..?

このファイル名は、私が PyRun_String() を使用しているためです。

4

2 に答える 2

3

以下の方法で解決しました。PyErr_Fetch() の後に PyErr_NormalizeException() を使用したところ、コードは正常に動作するようになりました。

int main(int argc, char** argv)
{
    Py_Initialize();

    // Get a reference to the main module.
    PyObject* main_module =
        PyImport_AddModule("__main__");

    // Get the main module's dictionary
    // and make a copy of it.
    PyObject* main_dict =
        PyModule_GetDict(main_module);

    const char *script_source = "def main():\n\tprint('Hello'\n\nmain()";

    PyObject *res = PyRun_String(script_source,Py_file_input,main_dict,main_dict);
    if(res == NULL)
    {
        PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;
        PyErr_Fetch(&ptype,&pvalue,&ptraceback);
        PyErr_NormalizeException(&ptype,&pvalue,&ptraceback);

        char *msg;
        char *file;
        int line;
        int offset;
        char *text;

        int res = PyArg_ParseTuple(pvalue,"s(siis)",&msg,&file,&line,&offset,&text);

        PyObject* file_name = PyObject_GetAttrString(pvalue,"filename");
        PyObject* file_name_str = PyObject_Str(file_name);
        PyObject* file_name_unicode = PyUnicode_AsEncodedString(file_name_str,"utf-8", "Error");
        char *actual_file_name = PyBytes_AsString(file_name_unicode);

        PyObject* line_no = PyObject_GetAttrString(pvalue,"lineno");
        PyObject* line_no_str = PyObject_Str(line_no);
        PyObject* line_no_unicode = PyUnicode_AsEncodedString(line_no_str,"utf-8", "Error");
        char *actual_line_no = PyBytes_AsString(line_no_unicode);

        printf("done");
    }
}
于 2013-05-29T05:57:09.560 に答える
1

属性はPySyntaxErrorObject 構造体に設定されますが、Python の安定した ABI に準拠している場合は構造体が公開されないことに注意してください。それ以外の場合は、 PyObject_GetAttr* 関数を使用して属性を取得できるはずです。

于 2013-05-27T02:12:13.450 に答える