Profilieren Sie einen Python-Code Zeile für Zeile
- Was ist Profiling
-
Profilieren Sie den Python-Code mit dem Modul
line_profiler
- Profilieren Sie Python-Code über die Befehlszeile
In diesem Artikel wird erläutert, wie jemand Python-Code Zeile für Zeile profilieren und nützliche Informationen zur Codeausführung erhalten kann.
Zuerst werden wir Profiling kurz vorstellen; Anschließend werden wir erörtern, wann die zeilenweise Profilerstellung besser zu verwenden ist als die funktionsbasierte Profilerstellung. Danach werden wir die Profiling-Implementierung in Python besprechen.
Was ist Profiling
Profiling ist der Prozess der Überprüfung der Ressourcen, die von verschiedenen Teilen unseres Codes verwendet werden. Für effiziente Codierungspraktiken befassen wir uns im Allgemeinen hauptsächlich entweder mit der Zeitkomplexität (Zeit, die von verschiedenen Codierungseinheiten/Funktionen benötigt wird) oder der Speicherkomplexität (Speichernutzung durch verschiedene Codierungseinheiten/Funktionen).
Ersteres hilft uns, uns darauf zu konzentrieren, die vom Programm benötigte Zeit zu reduzieren, und letzteres hilft uns, die Speichernutzung zu optimieren.
Funktionsprofilierung
Hauptsächlich in jeder Sprache wird die Erstellung von Profilen auf Funktionsebene verwendet, um die Zeit herauszufinden, die von verschiedenen Funktionen des Programms verbraucht wird. Daher enthält das Python-Standardpaket bereits die Bibliotheken cProfile
und Profile
für das Funktionsprofiling.
Linienprofiler
Der funktionsbasierte Profiler gibt Auskunft über die Zeit, die von den verschiedenen Funktionen benötigt wird. Manchmal benötigen wir jedoch eine zeilenbasierte Zeitkomplexität, um zu überprüfen, welche Zeile mehr zur Gesamtzeit beiträgt, die von der Funktion oder dem Programm benötigt wird.
Für so einen Fall haben wir die Bibliothek line_profiler
in Python.
Profilieren Sie den Python-Code mit dem Modul line_profiler
Das Modul LineProfiler
erlaubt uns, Code Zeile für Zeile oder nach Funktion zu profilieren.
Im folgenden Python-Code-Snippet haben wir zwei Funktionen namens slow_avg_producer()
und fast_average_producer()
erstellt. Diese beiden Funktionen erzeugen den gleichen Durchschnitt, aber ihre Ausführungszeit ist unterschiedlich.
Installieren Sie zunächst das folgende Modul, um den Code mithilfe des Leitungsprofilers zu profilieren.
!pip install line_profiler
import time
import random
def slow_avg_producer():
time.sleep(6) # Do nothing for 5 time units
# generate random numbers array
arr = [
random.randint(1, 100) for i in range(10000)
] # generate random numbers array
return sum(arr) / len(arr)
def fast_average_producer():
time.sleep(1) # Do nothing for 1 time units
# generate random numbers array
arr = [random.randint(1, 100) for i in range(10000)]
return sum(arr) / len(arr)
def main_func():
average = slow_avg_producer()
print(average)
result = fast_average_producer()
print(average)
Um die Timing-Statistiken zu erhalten, erstellen wir zuerst das Objekt LineProfiler
, dann wird das main_func()
durchlaufen, um den Wrapper zu erhalten. Am Ende können wir die Profiling-Statistiken erhalten.
from line_profiler import LineProfiler
line_prof = LineProfiler()
line_prof_wrapper = line_prof(main_func)
line_prof_wrapper()
# print the profiling details
line_prof.print_stats()
Der obige Code erzeugt die folgende Ausgabe. Die Zeiteinheit ist in Mikrosekunden.
Timer unit: 1e-06 s
Total time: 7.10521 s
File: <ipython-input-14-67ae2a9633ee>
Function: main_func at line 17
Line # Hits Time Per Hit % Time Line Contents
==============================================================
17 def main_func():
18 1 6054801.0 6054801.0 85.2 average = slow_avg_producer()
19 1 676.0 676.0 0.0 print(average)
20
21 1 1049070.0 1049070.0 14.8 result = fast_average_producer()
22 1 659.0 659.0 0.0 print(average)
Die Statistik zeigt, dass in der Hauptfunktion die slow_avg_producer()
6,054 Sekunden und die nächste print
-Anweisung 0,000676 Sekunden dauert. Dagegen benötigt fast_average_producer()
sehr viel weniger Zeit.
Profilieren Sie Python-Code über die Befehlszeile
Wir können die Befehlszeilenschnittstelle verwenden, um die zeilenweisen Profilierungsdetails der Funktionen abzurufen. Für diese Methode verwenden wir den Befehl kernprof
.
Wir werden auch hier die gleichen Funktionen verwenden, außer dass wir am Anfang jeder Funktion einen Dekorator, @profile
, hinzufügen. Wir nennen dieses Skript average_producer.py
.
import time
import random
@profile
def slow_avg_producer():
time.sleep(6) # Do nothing for 5 time units
# generate random numbers array
arr = [
random.randint(1, 100) for i in range(10000)
] # generate random numbers array
return sum(arr) / len(arr)
@profile
def fast_average_producer():
time.sleep(1) # Do nothing for 1 time units
# generate random numbers array
arr = [random.randint(1, 100) for i in range(10000)]
return sum(arr) / len(arr)
@profile
def main_func():
average = slow_avg_producer()
print(average)
result = fast_average_producer()
print(average)
main_func()
Mit dem Befehl kernprof
müssen wir das Modul line-profiler
mit dem folgenden Befehl installieren.
pip install line-profiler
Verwenden Sie für Colab- oder Jupyter-Notebook-Terminals das Bang-Symbol (!
) am Anfang des obigen Befehls.
Nach der Installation müssen Sie das Verzeichnis wechseln, in dem kernprof.exe
installiert ist. Führen Sie dann den folgenden Befehl aus.
kernprof
gibt uns die Möglichkeit, cProfile
zu machen, aber wir verwenden hier den Line-Profiler. Dafür wird das Argument -l
verwendet.
kernprof -l average_producer.py
Führen Sie den folgenden Befehl aus, um die Profilerstellungsergebnisse anzuzeigen.
python -m line_profiler average_producer.py.lprof
Es druckt die Profiling-Ergebnisse auf der Befehlszeilenschnittstelle, wie unten gezeigt.