2013-05-24 11 views
7

Mam wbudowany interpreter python w mojej aplikacji. Używam go do uruchamiania skryptów Pythona przy użyciu interfejsu API PyRun_String(). Mogę pobrać informacje o błędach za pomocą PyErr_Fetch(), jeśli napotkany zostanie błąd/wyjątek. Daje mi to typ wyjątku, wyjątek i wyjątek traceback. Następnie znajduję numer linii początkowego błędu z tracebacku. Jednak nie otrzymam żadnego rodzaju śledzenia w przypadku błędu składni. Czy ktoś wie, jak odzyskać numer linii bez traceback ..? Czy istnieje sposób odzyskania go za pomocą wyjątku lub wartości wyjątku ..?Jak pobrać nazwę pliku i atrybut lineno z SyntaxError

dokumentacji Python stwierdził, że:

Wystąpienia tej klasy posiadają atrybuty pliku, lineno, offset i tekst w celu łatwiejszego dostępu do informacji. str() instancji wyjątku zwraca tylko komunikat.

Jak mogę pobrać nazwę pliku i atrybut lineno z SyntaxError we wbudowanym python ..?

Każda pomoc zostanie doceniona. Z góry dziękuję.


Dzięki za sugestię, Brett. Ale już wypróbowałem to za pomocą PyObject_GetAttr().

Proszę zobaczyć poniższy przykładowy kod, którego użyłem do celów testowych.

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); 
    } 
} 

Mam celowo wstawił błąd składni w script_source.

Nie mogę pobrać rzeczywistej nazwy pliku i numeru linii z nazw plików nazwa_pliku i linii_no.

Próbowałem debugować file_name i line_no obiektów, a zawartość wygląda jak poniżej. "nazwa pliku składni błędów obiektów" i "składowa błędów obiektów składniowych"

Obiekty te nie są wywoływalne, więc nie mogę używać ich wariantów PyObject_Call().

Czy istnieje sposób, aby uzyskać rzeczywistą nazwę pliku i numer linii z tych obiektów ..?

W tym pliku nazwa będzie taka, jak używam PyRun_String().

Odpowiedz

3

Rozwiązałem go w następujący sposób. Użyłem PyErr_NormalizeException() po PyErr_Fetch() i kod działa dobrze teraz.

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"); 
    } 
} 
Powiązane problemy