2015-12-03 21 views
8

Mi piacerebbe creare un'applicazione con interprete python incorporato e funzionalità di debug di base. Ora sto cercando l'API per le funzioni che potrei usare per eseguire il codice di esecuzione e ottenere il numero della riga corrente del codice che è in corso (o sta per essere) eseguita.Esecuzione del codice di traccia nell'interprete Python incorporato

I documenti Python ufficiali sembrano essere un po 'sottotono per me quando arriva a tracing and profiling. Non esiste, ad esempio, alcuna informazione sul significato del valore di ritorno di Py_tracefunc.

Finora ho montato il seguente:

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

Tuttavia, il compilatore emette il seguente errore:

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

sto operando su ManjaroLinux e utilizzando il seguente per compilare il sopra :

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 

ho trovato che posso sostituire PyFrameObject con struct _frame e poi programma la compilazione ma tutti sanno che si tratta di un trucco sporco, non di una soluzione.

Le uscite eseguibile seguenti:

line 1 
line 2 
line 3 
line 4 
line 5 
7 

Ma vuoi le tracce di seguire il flusso di esecuzione dello script (cioè: Iniziamo dalla linea 3, poi 4, 5 e poi, a causa alla chiamata di funzione, 2).

Non sono riuscito a trovare nulla sull'esecuzione passo-passo.

Potresti raccomandare altre fonti sull'API Python C con maggiori informazioni e qualche introduzione all'argomento?

Ho assegnato la risposta con taglia poiché sarebbe scaduta lo stesso. Tuttavia, sto ancora cercando e sarei grato per le risposte ad altre domande dall'alto.

+2

Questo potrebbe aiutare per quanto riguarda la funzione di traccia: https://docs.python.org/3/library/sys.html#sys.settrace –

+2

Oltre a ciò, utilizzare la fonte, Luke! –

+0

@SvenMarnach: intendi file di intestazione Python? – Luke

risposta

8
hello.c:5:26: error: unknown type name ‘PyFrameObject’ 

Questo errore significa che PyFrameObject non era stata dichiarata. Ho fatto uno Google search che mi ha mostrato frameobject.h nell'albero dei sorgenti Python dove viene dichiarata la struttura.

mi aspetto che si può aggiungere la riga

#include <frameobject.h> 

per risolvere questo.

+0

Ho letto da qualche parte su Internet che solo Python.h dovrebbe essere sufficiente. L'esempio dei documenti include anche solo Python.h. – Luke

+1

Potrebbe fornire una fonte che sostenga che frameobject.h debba essere incluso separatamente? – Luke

+0

L'ho dedotto dal messaggio di errore che hai postato. Puoi determinare da solo leggendo la fonte. Leggi Python.h e segui i vari include per vedere dove/se include frameobject.h. Potrebbe anche essere condizionale basato su token di preprocessore definiti. – dsh

-1

PyFrameObject è solo una struttura _frame. È sufficiente sostituire PyFrameObject per _frame nella firma della funzione e non sarà necessario includere ulteriori intestazioni python.

0

Il pyFrameObject ha un campo

int f_lineno; 

. Puoi usarlo.Ma a quanto pare, non sta sempre memorizzando il valore corretto. Quindi, probabilmente si dovrebbe utilizzare la funzione:

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

allora, è possibile utilizzare

frame->f_code->co_filename 

per ottenere il nome del file corrente

frame->f_code->co_name 

per ottenere il nome della funzione corrente e

frame->f_back 

per ottenere un livello inferiore nello stack di chiamate. .

Problemi correlati