2015-12-03 3 views
8

Ich möchte eine Anwendung mit eingebetteten Python-Interpreter und grundlegenden Debugging-Funktionen erstellen. Jetzt suche ich die API nach Funktionen, die ich verwenden könnte, Code Schritt für Schritt ausführen und die Nummer der aktuellen Zeile Code erhalten, die gerade ausgeführt wird (oder gerade ausgeführt wird).Verfolgen von Code-Ausführung in eingebetteten Python-Interpreter

Offizielle Python-Dokumente scheinen ein wenig unterentwickelt für mich, wenn es zu tracing and profiling kommt. Es gibt zum Beispiel keine Informationen über die Bedeutung des Rückgabewertes Py_tracefunc.

Bisher habe ich folgendes zusammengesetzt:

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

jedoch der Compiler gibt den folgenden Fehler:

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

Ich bin auf Manjaro Linux arbeitet und mit der im Anschluss an die oben zu kompilieren :

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 

ich habe festgestellt, dass ichersetzen 0 mit struct _frame und dann Programm kompiliert, aber jeder weiß, es ist ein schmutziger Hack, keine Lösung.

Die ausführbare Datei gibt die folgende:

line 1 
line 2 
line 3 
line 4 
line 5 
7 

Aber ich die Spuren möchten den Ausführungsablauf des Skripts folgen (das heißt: von der Linie 3 starten, dann 4, 5 und dann durch zum Funktionsaufruf, 2).

Ich konnte nichts über Schritt-für-Schritt-Ausführung finden.

Können Sie weitere Quellen zur Python C API mit weiteren Informationen und einer Einführung in das Thema empfehlen?

Ich vergab die Antwort mit Kopfgeld, da es sowieso ablaufen würde. Ich schaue aber immer noch nach und wäre dankbar für Antworten auf andere Fragen von oben.

+2

Dies könnte in Bezug auf die Trace-Funktion helfen: https://docs.python.org/3/library/sys.html#sys.settrace –

+2

Abgesehen davon, verwenden Sie die Quelle, Luke! –

+0

@SvenMarnach: meinst du Python-Header-Dateien? – Luke

Antwort

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

Dieser Fehler bedeutet, dass PyFrameObject wurde nicht deklariert. Ich habe eine Google search, die zeigte mir frameobject.h in der Python-Source-Struktur ist, wo diese Struktur deklariert ist.

Ich gehe davon aus, dass Sie die Zeile hinzufügen können

#include <frameobject.h> 

dieses Problem zu beheben.

+0

Ich habe irgendwo im Internet gelesen, dass Python.h alleine ausreichen sollte. Das Beispiel aus der Dokumentation enthält auch nur Python.h. – Luke

+1

Könnten Sie eine Quelle angeben, die behauptet, dass frameobject.h getrennt aufgeführt werden sollte? – Luke

+0

Ich habe es von der Fehlermeldung abgeleitet, die Sie gepostet haben. Sie können selbst bestimmen, indem Sie die Quelle lesen. Lies Python.h und folge den verschiedenen Includes, um zu sehen, wo/ob es frameobject.h enthält. Es könnte sogar basierend auf definierten Präprozessor-Tokens konditional sein. – dsh

-1

PyFrameObject ist nur ein _frame struct. Ersetzen Sie einfach PyFrameObject durch _frame in Ihrer Funktionssignatur und Sie müssen keine zusätzlichen Python-Header hinzufügen.

0

Die pyFrameObject hat ein

int f_lineno; 

Feld. Sie können es verwenden.Aber anscheinend speichert es nicht immer den richtigen Wert. Also, sollten Sie wahrscheinlich die Funktion verwenden:

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

dann können Sie

frame->f_code->co_filename 

verwenden, um die aktuellen Dateinamen zu bekommen

frame->f_code->co_name 

erhält die aktuellen Funktionsnamen und

frame->f_back 

um eine Ebene tiefer in den Aufrufstapel zu bekommen. .

Verwandte Themen