Tracing der Funktionsaufrufe in Python

Hallo zusammen, ich interessiere mich dafür, welche Python Funktion/Methode welche C Funktionen im Kern des CPython Interpreters aufruft (voller Call Stack) und zusätzlich auch für das Profiling dieser C Funktionen. Leider konnte ich bisher für diesen Zweck kein Modul finden. Nehmen wir das Beispiel der print Funktion in Python3. Letztlich ruft diese, wenn ich den Source Code CPythons richtig verstehe die Funktion builtin_print (definiert in Python/bltinmodule.c) auf. Diese Funktion wiederum nutzt Funktionen aus der Python C API, wie bspw. PyArg_ParseTupleAndKeywords zum Auslesen der übergebenen Parameter, oder PyFile_WriteObject zum Schreiben des Inputs in den entsprechenden Outputstream. PyFile_WriteObject wiederum holt sich das Attribut "write" des Outputstream Objekts und ruft dann PyEval_CallObject darauf auf, usw. Ein Modul, das mir diesen Function Stack transparent machen plus ein bis auf die C Ebene aufgeschlüsseltes Profiling anbieten würde, wäre eine feine Sache. Bisher habe ich mich ohne Erfolg an pdb, vmprof, dem Bauen CPythons mit dem debug flag und ltrace versucht. Sicherlich gäbe es die Möglichkeit mittels gdb oder valgrind an diese Call Stacks heranzukommen, aber diese Tools sind nicht gerade leichtgewichtig. Kennt jemand mögliche Techniken / Module, die mir dies ermöglichen, oder ist es wirklich nur durch Studium des Interpreter-Quellcodes möglich? -- Mit freundlichen Grüßen/best regards Christian Junker

Hallo, Ich habe mal aus Spass fuer den LLDB einen Stacktrace Analyzer gebaut, mit dem man im LLDB den Python-Stacktrace bekommt. Das ist also quasi die Kombination aus lldb + pdb. In Grenzen. Aber fuer ein solches Tracing koennte es funktionieren. Ob es einfacher ist als das haendische rausfummeln musst du entscheiden. Und wie immer bei solchen Problemen stellt sich die Frage nach dem “warum” - wenn du das beleuchten wuerdest, koennte man ggf. alternative Herangehensweisen vorschlagen. Diez
On 3 Nov 2016, at 11:57, Christian Junker <christianjunker@gmail.com> wrote:
Hallo zusammen,
ich interessiere mich dafür, welche Python Funktion/Methode welche C Funktionen im Kern des CPython Interpreters aufruft (voller Call Stack) und zusätzlich auch für das Profiling dieser C Funktionen. Leider konnte ich bisher für diesen Zweck kein Modul finden.
Nehmen wir das Beispiel der print Funktion in Python3. Letztlich ruft diese, wenn ich den Source Code CPythons richtig verstehe die Funktion builtin_print (definiert in Python/bltinmodule.c) auf. Diese Funktion wiederum nutzt Funktionen aus der Python C API, wie bspw. PyArg_ParseTupleAndKeywords zum Auslesen der übergebenen Parameter, oder PyFile_WriteObject zum Schreiben des Inputs in den entsprechenden Outputstream. PyFile_WriteObject wiederum holt sich das Attribut "write" des Outputstream Objekts und ruft dann PyEval_CallObject darauf auf, usw.
Ein Modul, das mir diesen Function Stack transparent machen plus ein bis auf die C Ebene aufgeschlüsseltes Profiling anbieten würde, wäre eine feine Sache. Bisher habe ich mich ohne Erfolg an pdb, vmprof, dem Bauen CPythons mit dem debug flag und ltrace versucht. Sicherlich gäbe es die Möglichkeit mittels gdb oder valgrind an diese Call Stacks heranzukommen, aber diese Tools sind nicht gerade leichtgewichtig.
Kennt jemand mögliche Techniken / Module, die mir dies ermöglichen, oder ist es wirklich nur durch Studium des Interpreter-Quellcodes möglich?
-- Mit freundlichen Grüßen/best regards Christian Junker _______________________________________________ python-de maillist - python-de@python.org https://mail.python.org/mailman/listinfo/python-de

Hallo Christian! Christian Junker schrieb am 03.11.2016 um 11:57:
ich interessiere mich dafür, welche Python Funktion/Methode welche C Funktionen im Kern des CPython Interpreters aufruft (voller Call Stack) und zusätzlich auch für das Profiling dieser C Funktionen.
Interessiert dich das nur einfach mal so, oder verfolgst du damit irgendein Ziel?
Leider konnte ich bisher für diesen Zweck kein Modul finden.
Nehmen wir das Beispiel der print Funktion in Python3. Letztlich ruft diese, wenn ich den Source Code CPythons richtig verstehe die Funktion builtin_print (definiert in Python/bltinmodule.c) auf. Diese Funktion wiederum nutzt Funktionen aus der Python C API, wie bspw. PyArg_ParseTupleAndKeywords zum Auslesen der übergebenen Parameter, oder PyFile_WriteObject zum Schreiben des Inputs in den entsprechenden Outputstream. PyFile_WriteObject wiederum holt sich das Attribut "write" des Outputstream Objekts und ruft dann PyEval_CallObject darauf auf, usw.
print() ist vielleicht nicht das interessanteste für's Profiling, aber im Wesentlichen stimmt das, was du schreibst (zumindest vor CPython 3.6, das für die Funktionseinstiegspunkte im Build besseren Code generiert als die "PyArg_*" Funktionsaufrufe).
Ein Modul, das mir diesen Function Stack transparent machen plus ein bis auf die C Ebene aufgeschlüsseltes Profiling anbieten würde, wäre eine feine Sache. Bisher habe ich mich ohne Erfolg an pdb, vmprof, dem Bauen CPythons mit dem debug flag und ltrace versucht. Sicherlich gäbe es die Möglichkeit mittels gdb oder valgrind an diese Call Stacks heranzukommen, aber diese Tools sind nicht gerade leichtgewichtig.
Kennt jemand mögliche Techniken / Module, die mir dies ermöglichen, oder ist es wirklich nur durch Studium des Interpreter-Quellcodes möglich?
Unter Linux verwende ich für solche Sachen entweder callgrind (Profiler in valgrind) zusammen mit Kcachegrind zur Visualisierung, oder perf. Letzteres ist ein recht leicht zu benutzender statistischer Profiler, bei dem du per Text-Interface durch die Aufrufe hindurch springen kannst. callgrind liefert dir dagegen ein komplettes Laufprofil, braucht dadurch etwas länger, aber bietet mit Kcachegrind eine schicke grafische Oberfläche zum Hineinklicken. Um zu verstehen, was vor sich geht, ist das eins der besten (kostenfreien) Tools, die ich kenne. Wichtig ist, dass du bei callgrind per "--toggle-collect=NAME" einen Funktionsnamen angeben kannst, innerhalb der der Profiler angeworfen wird. Alles andere wird dann ignoriert und verschwendet keine Laufzeit. Ansonsten gibt es auch noch Intels vprof, für das OSS-Entwickler unter bestimmten Umständen eine kostenlose Lizenz bekommen können. Ist recht gut und verbindet die Vorteile der Tools oben (statistisch + grafisch), aber die beiden tun's im Wesentlichen auch, je nach Anwendungsfall. Stefan

Hallo Stefan, ich bin beruflich sehr stark auf Windows NT unterwegs. In den industriellen Großprojekten im PDM/PLM Umfeld besteht zum einen die Transition von kommerziellen Unix Servern, wie Solaris, hin zu Linux, zum anderen ist der Betrieb von Windows Server Distributionen häufig anzutreffen (besonders für neuere Projekte im Mittelstand (KMU), z.B. einer PLM Systemeinführung, wo es evt. keine Unix/Linux Administratoren gibt). Insofern sind mir das ein oder andere Mal die Hände gebunden, wenn es um Monitoring und Profiling Werkzeuge geht, die die Interna der Software sichtbar machen. Das einzige Tool, das ich unter Windows als Sampling Profiler nützlich finde, ist verysleepy. Es funktioniert allerdings nicht so gut für den Python Interpreter. Die Gründe für meine Anfrage sind unterschiedlicher Natur: Zum einen geht es ganz konkret um ein besseres Verständnis der Python C API, auch weil ich zu den großen PLM APIs kein direktes Python Binding habe. Ich kann mir Python hier nicht nur als Automatisierungstool für große Datenmigrationen vorstellen, sondern auch als Test Framework, um gewisse Grundfunktionalitäten des oftmals stark gecustomizeten/erweiterten Systems effizient testen zu können. Vor einiger Zeit hatte ich solch ein Toolkit begonnen, damals mit cffi. Zum anderen ist es der Reiz auch für Python hinter die Bühne zu sehen. Ich teile die Meinung nicht, dass man aus Gründen der Komplexität die Finger von C Extensions lassen sollte, auch wenn Cython und boost python sicher ihren Charme haben. Ich kann mir auch gut vorstellen, dass die so ermöglichte Transparenz für Schulungszwecke genutzt werden kann, um Studenten neben Python auch C als wichtige Programmiersprache zu vermitteln. Dass der Python-Interpreter im debug Modus so viel ausdruckt, aber den Call Stack in C nicht, kann ich jedenfalls nicht verstehen. Ein weiterer Punkt dürfte all jene betreffen, die Python in ihrer C++ Applikation embedden möchten. Ich habe mit cffi, ctypes und anderen Modulen z.B. das Problem, dass ich wrapper Funktionen in C implementieren muss, weil ich C++ Klassen und Methoden nicht direkt nutzen kann. BTW: Käme es nicht auch der Entwicklung des Cython Cores entgegen? Schließlich muss der ja die Python Skripte in C Code umwandeln. Und das geht ja an vielen Stellen nur durch ein tiefes Wissen über die Python C API. Statt hierfür ständig auf externe Tools wie callgrind zurückgreifen zu müssen, wäre es doch für den typischen iterativen Round Trip an Entwicklungsaufgaben schöner, die C Funktionen direkt im Interpreter zu sehen, sobald man eine Funktion interaktiv aufruft. Am 3. November 2016 um 20:32 schrieb Stefan Behnel <python-de@behnel.de>:
Hallo Christian!
Christian Junker schrieb am 03.11.2016 um 11:57:
ich interessiere mich dafür, welche Python Funktion/Methode welche C Funktionen im Kern des CPython Interpreters aufruft (voller Call Stack) und zusätzlich auch für das Profiling dieser C Funktionen.
Interessiert dich das nur einfach mal so, oder verfolgst du damit irgendein Ziel?
Leider konnte ich bisher für diesen Zweck kein Modul finden.
Nehmen wir das Beispiel der print Funktion in Python3. Letztlich ruft diese, wenn ich den Source Code CPythons richtig verstehe die Funktion builtin_print (definiert in Python/bltinmodule.c) auf. Diese Funktion wiederum nutzt Funktionen aus der Python C API, wie bspw. PyArg_ParseTupleAndKeywords zum Auslesen der übergebenen Parameter, oder PyFile_WriteObject zum Schreiben des Inputs in den entsprechenden Outputstream. PyFile_WriteObject wiederum holt sich das Attribut "write" des Outputstream Objekts und ruft dann PyEval_CallObject darauf auf, usw.
print() ist vielleicht nicht das interessanteste für's Profiling, aber im Wesentlichen stimmt das, was du schreibst (zumindest vor CPython 3.6, das für die Funktionseinstiegspunkte im Build besseren Code generiert als die "PyArg_*" Funktionsaufrufe).
Ein Modul, das mir diesen Function Stack transparent machen plus ein bis auf die C Ebene aufgeschlüsseltes Profiling anbieten würde, wäre eine feine Sache. Bisher habe ich mich ohne Erfolg an pdb, vmprof, dem Bauen CPythons mit dem debug flag und ltrace versucht. Sicherlich gäbe es die Möglichkeit mittels gdb oder valgrind an diese Call Stacks heranzukommen, aber diese Tools sind nicht gerade leichtgewichtig.
Kennt jemand mögliche Techniken / Module, die mir dies ermöglichen, oder ist es wirklich nur durch Studium des Interpreter-Quellcodes möglich?
Unter Linux verwende ich für solche Sachen entweder callgrind (Profiler in valgrind) zusammen mit Kcachegrind zur Visualisierung, oder perf.
Letzteres ist ein recht leicht zu benutzender statistischer Profiler, bei dem du per Text-Interface durch die Aufrufe hindurch springen kannst.
callgrind liefert dir dagegen ein komplettes Laufprofil, braucht dadurch etwas länger, aber bietet mit Kcachegrind eine schicke grafische Oberfläche zum Hineinklicken. Um zu verstehen, was vor sich geht, ist das eins der besten (kostenfreien) Tools, die ich kenne. Wichtig ist, dass du bei callgrind per "--toggle-collect=NAME" einen Funktionsnamen angeben kannst, innerhalb der der Profiler angeworfen wird. Alles andere wird dann ignoriert und verschwendet keine Laufzeit.
Ansonsten gibt es auch noch Intels vprof, für das OSS-Entwickler unter bestimmten Umständen eine kostenlose Lizenz bekommen können. Ist recht gut und verbindet die Vorteile der Tools oben (statistisch + grafisch), aber die beiden tun's im Wesentlichen auch, je nach Anwendungsfall.
Stefan
_______________________________________________ python-de maillist - python-de@python.org https://mail.python.org/mailman/listinfo/python-de
-- Mit freundlichen Grüßen/best regards Christian Junker

On Donnerstag, 3. November 2016 22:01:44 Christian Junker wrote:
Ein weiterer Punkt dürfte all jene betreffen, die Python in ihrer C++ Applikation embedden möchten. Ich habe mit cffi, ctypes und anderen Modulen z.B. das Problem, dass ich wrapper Funktionen in C implementieren muss, weil ich C++ Klassen und Methoden nicht direkt nutzen kann.
Phil Thompson hat hierzu ein "binding tool" erstellt, der sehr effizient C++ Module einbindet: sip. Meiner Ansicht nach findet dieses Tool (und ein paar Andere aus der Familie) zu wenig Beachtung. Mit Hilfe von sip werden z.B. die PyQt{3,4,5} bindings erstellt. Anders als swig kommt es ohne Trampolin-Python Module aus, etc.. Zum Tracen auf C Ebene tat es bei mir bislang callgrind und friends. Ich denke, dass für Leute, die so tief blicken wollen, vorausgesetzt wird, dass diese auch die entspechenden Werkzeuge beherschen. Interessanterweise gabs es ja schon einige Ansätze zum Reverse Engineering mit Python, aber das ist eine andere Geschichte.. ;) Pete
participants (4)
-
Christian Junker
-
Diez B. Roggisch
-
Hans-Peter Jansen
-
Stefan Behnel