Running trace code in the Python built-in interpreter

I would like to create an application with a built-in python interpreter and basic debugging capabilities. Now I am looking for an API for functions that I can use to run the code step by step and get the number of the current line of code that is being executed (or should be) executed.

The Python white papers seem a bit underestimated to me when it comes to tracing and profiling . For example, there is no information about the value of the return value of Py_tracefunc .

So far I have compiled the following:

 #include <Python.h> static int lineCounter = 0; int trace(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) { if(what == PyTrace_LINE) { lineCounter += 1; printf("line %d\n", lineCounter); } return 0; } int main(int argc, char *argv[]) { wchar_t *program = Py_DecodeLocale(argv[0], NULL); if (program == NULL) { fprintf(stderr, "Fatal error: cannot decode argv[0]\n"); exit(1); } Py_SetProgramName(program); /* optional but recommended */ Py_Initialize(); PyEval_SetTrace(trace, NULL); char *code = "def adder(a, b):\n" " return a + b\n" "x = 3\n" "y = 4\n" "print(adder(x, y))\n"; PyRun_SimpleString(code); Py_Finalize(); PyMem_RawFree(program); return 0; } 

However, the compiler generates the following error:

 hello.c:5:26: error: unknown type name 'PyFrameObject' int trace(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) ^ 

I work on ManjaroLinux and use the following to compile above:

 gcc -o hello hello.c -I/usr/include/python3.5m -Wno-unused-result -Wsign-compare -Wunreachable-code -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -L/usr/lib -lpython3.5m -lpthread -ldl -lutil -lm -Xlinker -export-dynamic 

I found that I can replace PyFrameObject with struct _frame and then compile the programs, but everyone knows that this is a dirty hack, not a solution.

The executable file displays the following:

 line 1 line 2 line 3 line 4 line 5 7 

But I would like the traces to follow the script execution flow (i.e.: starting from line 3, then 4, 5, and then due to the function 2 call).

I could not find anything about step-by-step execution.

Could you recommend other sources about the Python C API with additional information and some introduction to the topic?

I rewarded the answer with generosity, as it will expire anyway. However, I still look and will be grateful for answers to other questions from above.

+8
c python python-c-api
source share
3 answers
 hello.c:5:26: error: unknown type name 'PyFrameObject' 

This error means that PyFrameObject not been declared. I did a google search that showed me frameobject.h in the Python source tree where this structure is declared.

I expect you can add a line

 #include <frameobject.h> 

to solve this problem.

+8
source share

In pyFrameObject there is

 int f_lineno; 

field. You can use it. But, apparently, it does not always retain the correct meaning. So you should probably use a function:

 /* Return the line of code the frame is currently executing. */ int PyFrame_GetLineNumber(PyFrameObject *); 

then you can use

 frame->f_code->co_filename 

to get the current file name

 frame->f_code->co_name 

to get the current function name and

 frame->f_back 

to get one level down in the call stack. .

0
source share

PyFrameObject is just a _frame structure. Just replace PyFrameObject with _frame in your function signature and you won’t have to include any additional python headers.

-one
source share

All Articles