Profilieren Sie einen Python-Code Zeile für Zeile

Hafiz Muhammad Zohaib 15 Februar 2024
  1. Was ist Profiling
  2. Profilieren Sie den Python-Code mit dem Modul line_profiler
  3. Profilieren Sie Python-Code über die Befehlszeile
Profilieren Sie einen Python-Code Zeile für Zeile

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.

Line-Profiler installieren

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

kernprof

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.

Python-Line-Profiler

Profiling-Ergebnisse

Verwandter Artikel - Python Profile