Immagine dell'autore
Come sviluppatore di software, probabilmente avrai sentito la citazione “L’ottimizzazione prematura è la radice di tutti i mali”-più di una volta-nella tua carriera. Anche se l’ottimizzazione potrebbe non essere molto utile (o assolutamente necessaria) per i piccoli progetti, la profilazione è spesso utile.
Dopo aver terminato la codifica di un modulo, è buona norma profilare il codice per misurare il tempo necessario per l'esecuzione di ciascuna sezione. Ciò può aiutare a identificare gli odori del codice e guidare le ottimizzazioni per migliorare la qualità del codice. Quindi profila sempre il tuo codice prima di ottimizzare!
Per muovere i primi passi, questa guida ti aiuterà a iniziare con la profilazione in Python, utilizzando il built-in timeit ed cProfilo moduli. Imparerai a utilizzare sia l'interfaccia della riga di comando che i richiamabili equivalenti all'interno degli script Python.
Il modulo timeit fa parte della libreria standard Python e offre alcune funzioni utili che possono essere utilizzate per cronometrare brevi frammenti di codice.
Facciamo un semplice esempio di inversione di una lista Python. Misureremo i tempi di esecuzione per ottenere una copia invertita della lista utilizzando:
- , il
reversed()
funzione e - elenco affettamento.
>>> nums=[6,9,2,3,7]
>>> list(reversed(nums))
[7, 3, 2, 9, 6]
>>> nums[::-1]
[7, 3, 2, 9, 6]
Esecuzione di Timeit dalla riga di comando
Puoi correre timeit
alla riga di comando utilizzando la sintassi:
$ python -m timeit -s 'setup-code' -n 'number' -r 'repeat' 'stmt'
Ti viene richiesto di fornire la dichiarazione stmt
il cui tempo di esecuzione deve essere misurato.
Puoi specificare il setup
codice quando necessario, utilizzando l'opzione breve -s o l'opzione lunga –setup. Il codice di installazione verrà eseguito una sola volta.
Il number
di volte per eseguire l'istruzione: l'opzione breve -n o l'opzione lunga –number è facoltativa. E il numero di volte per ripetere questo ciclo: anche l'opzione breve -r o l'opzione lunga –repeat è facoltativa.
Vediamo quanto sopra in azione per il nostro esempio:
Qui la creazione dell'elenco è il setup
codice e invertendo l'elenco è l'istruzione da cronometrare:
$ python -m timeit -s 'nums=[6,9,2,3,7]' 'list(reversed(nums))'
500000 loops, best of 5: 695 nsec per loop
Quando non specifichi valori per repeat
, viene utilizzato il valore predefinito 5. E quando non lo specifichi number
, il codice viene eseguito tante volte quanto necessario in modo da raggiungere un tempo totale di almeno 0.2 secondi.
Questo esempio imposta esplicitamente il numero di volte per eseguire l'istruzione:
$ python -m timeit -s 'nums=[6,9,2,3,7]' -n 100Bu000 'list(reversed(nums))'
100000 loops, best of 5: 540 nsec per loop
Il valore predefinito di repeat
è 5, ma possiamo impostarlo su qualsiasi valore adatto:
$ python3 -m timeit -s 'nums=[6,9,2,3,7]' -r 3 'list(reversed(nums))'
500000 loops, best of 3: 663 nsec per loop
Cronometramo anche l'approccio di suddivisione dell'elenco:
$ python3 -m timeit -s 'nums=[6,9,2,3,7]' 'nums[::-1]'
1000000 loops, best of 5: 142 nsec per loop
L'approccio di suddivisione in elenchi sembra essere più veloce (tutti gli esempi sono in Python 3.10 su Ubuntu 22.04).
Esecuzione di timeit in uno script Python
Ecco l'equivalente dell'esecuzione di timeit all'interno dello script Python:
import timeit setup = 'nums=[9,2,3,7,6]'
number = 100000
stmt1 = 'list(reversed(nums))'
stmt2 = 'nums[::-1]' t1 = timeit.timeit(setup=setup,stmt=stmt1,number=number)
t2 = timeit.timeit(setup=setup,stmt=stmt2,number=number) print(f"Using reversed() fn.: {t1}")
print(f"Using list slicing: {t2}")
Il timeit()
callable restituisce il tempo di esecuzione di stmt
per number
di volte. Si noti che possiamo menzionare esplicitamente il numero di volte da eseguire o effettuare number
prendi il valore predefinito di 1000000.
Output >>
Using reversed() fn.: 0.08982690000000002
Using list slicing: 0.015550800000000004
Questo esegue l'istruzione, senza ripetere la funzione timer, per l'oggetto specificato number
di volte e restituisce il tempo di esecuzione. È anche abbastanza comune da usare time.repeat()
e prenditi il tempo minimo come mostrato:
import timeit setup = 'nums=[9,2,3,7,6]'
number = 100000
stmt1 = 'list(reversed(nums))'
stmt2 = 'nums[::-1]' t1 = min(timeit.repeat(setup=setup,stmt=stmt1,number=number))
t2 = min(timeit.repeat(setup=setup,stmt=stmt2,number=number)) print(f"Using reversed() fn.: {t1}")
print(f"Using list slicing: {t2}")
Questo ripeterà il processo di esecuzione del codice number
di volte repeat
numero di volte e restituisce il tempo di esecuzione minimo. Qui abbiamo 5 ripetizioni da 100000 volte ciascuna.
Output >>
Using reversed() fn.: 0.055375300000000016
Using list slicing: 0.015101400000000043
Abbiamo visto come timeit può essere utilizzato per misurare i tempi di esecuzione di brevi snippet di codice. Tuttavia, in pratica, è più utile profilare un intero script Python.
Questo ci fornirà i tempi di esecuzione di tutte le funzioni e le chiamate ai metodi, inclusi funzioni e metodi integrati. In questo modo possiamo avere un'idea migliore delle chiamate di funzioni più costose e identificare le opportunità di ottimizzazione. Ad esempio: potrebbe esserci una chiamata API troppo lenta. Oppure una funzione può avere un ciclo che può essere sostituito da un'espressione di comprensione più pythonica.
Impariamo come profilare gli script Python utilizzando il modulo cProfile (anch'esso parte della libreria standard Python).
Considera il seguente script Python:
# main.py
import time def func(num): for i in range(num): print(i) def another_func(num): time.sleep(num) print(f"Slept for {num} seconds") def useful_func(nums, target): if target in nums: return nums.index(target) if __name__ == "__main__": func(1000) another_func(20) useful_func([2, 8, 12, 4], 12)
Qui abbiamo tre funzioni:
func()
che scorre attraverso una serie di numeri e li stampa.another func()
che contiene una chiamata alsleep()
funzione.useful_func()
che restituisce l'indice di un numero di target in lista (se il target è presente nella lista).
Le funzioni sopra elencate verranno chiamate ogni volta che esegui lo script main.py.
Esecuzione di cProfile dalla riga di comando
Esegui cProfile dalla riga di comando utilizzando:
python3 -m file-name.py
Qui abbiamo chiamato il file main.py:
python3 -m main.py
L'esecuzione di questo dovrebbe darti il seguente output:
Output >> 0 ... 999 Slept for 20 seconds
E il seguente profilo:
Qui, ncalls
si riferisce al numero di chiamate alla funzione e percall
si riferisce al tempo per chiamata di funzione. Se il valore di ncalls
è maggiore di uno, quindi percall
è il tempo medio tra tutte le chiamate.
Il tempo di esecuzione dello script è dominato da another_func
che utilizza il built-in sleep
chiamata di funzione (dorme per 20 secondi). Lo vediamo print
anche le chiamate di funzione sono piuttosto costose.
Utilizzo di cProfile nello script Python
Sebbene l'esecuzione di cProfile dalla riga di comando funzioni correttamente, puoi anche aggiungere la funzionalità di profilazione allo script Python. Puoi usare cProfile accoppiato con il modulo pstat per la profilazione e l’accesso alle statistiche.
Come best practice per gestire meglio la configurazione e lo smontaggio delle risorse, utilizzare l'istruzione with e creare un oggetto profilo da utilizzare come gestore del contesto:
# main.py
import pstats
import time
import cProfile def func(num): for i in range(num): print(i) def another_func(num): time.sleep(num) print(f"Slept for {num} seconds") def useful_func(nums, target): if target in nums: return nums.index(target) if __name__ == "__main__": with cProfile.Profile() as profile: func(1000) another_func(20) useful_func([2, 8, 12, 4], 12) profile_result = pstats.Stats(profile) profile_result.print_stats()
Diamo uno sguardo più da vicino al profilo di output generato:
Quando stai profilando uno script di grandi dimensioni, sarà utile ordinare i risultati in base al tempo di esecuzione. Per farlo puoi chiamare sort_stats
sull'oggetto del profilo e ordinarlo in base al tempo di esecuzione:
...
if __name__ == "__main__": with cProfile.Profile() as profile: func(1000) another_func(20) useful_func([2, 8, 12, 4], 12) profile_result = pstats.Stats(profile) profile_result.sort_stats(pstats.SortKey.TIME) profile_result.print_stats()
Quando ora esegui lo script, dovresti essere in grado di vedere i risultati ordinati per ora:
Spero che questa guida ti aiuti a iniziare con la profilazione in Python. Ricorda sempre che le ottimizzazioni non dovrebbero mai andare a scapito della leggibilità. Se sei interessato a conoscere altri profiler, inclusi i pacchetti Python di terze parti, dai un'occhiata a questo articolo sui profiler Python.
Bala Priya C è uno sviluppatore e scrittore tecnico dall'India. Le piace lavorare all'intersezione tra matematica, programmazione, scienza dei dati e creazione di contenuti. Le sue aree di interesse e competenza includono DevOps, data science ed elaborazione del linguaggio naturale. Le piace leggere, scrivere, programmare e il caffè! Attualmente, sta lavorando all'apprendimento e alla condivisione delle sue conoscenze con la comunità degli sviluppatori creando tutorial, guide pratiche, articoli di opinione e altro ancora.
- Distribuzione di contenuti basati su SEO e PR. Ricevi amplificazione oggi.
- PlatoData.Network Generativo verticale Ai. Potenzia te stesso. Accedi qui.
- PlatoAiStream. Intelligenza Web3. Conoscenza amplificata. Accedi qui.
- PlatoneESG. Automobilistico/VE, Carbonio, Tecnologia pulita, Energia, Ambiente, Solare, Gestione dei rifiuti. Accedi qui.
- Platone Salute. Intelligence sulle biotecnologie e sulle sperimentazioni cliniche. Accedi qui.
- Grafico Prime. Migliora il tuo gioco di trading con ChartPrime. Accedi qui.
- BlockOffset. Modernizzare la proprietà della compensazione ambientale. Accedi qui.
- Fonte: https://www.kdnuggets.com/profiling-python-code-using-timeit-and-cprofile?utm_source=rss&utm_medium=rss&utm_campaign=profiling-python-code-using-timeit-and-cprofile
- :È
- :non
- 10
- 100000
- 12
- 13
- 15%
- 17
- 19
- 20
- 22
- 7
- 8
- 9
- a
- capace
- Chi siamo
- sopra
- assolutamente
- Accedendo
- ACM
- operanti in
- Action
- aggiungere
- Tutti
- anche
- sempre
- an
- ed
- in qualsiasi
- api
- approccio
- SONO
- aree
- AS
- At
- autore
- media
- basato
- BE
- prima
- MIGLIORE
- Meglio
- entrambi
- incassato
- ma
- by
- chiamata
- detto
- Bandi
- Materiale
- Può ottenere
- Career
- CFM
- dai un'occhiata
- più vicino
- codice
- codifica
- Venire
- Uncommon
- comunità
- contiene
- contenuto
- creazione di contenuti
- contesto
- comodità
- Costo
- accoppiato
- creare
- Creazione
- creazione
- Attualmente
- ciclo
- dati
- scienza dei dati
- Predefinito
- Costruttori
- DevOps
- do
- Dont
- ogni
- Intero
- Equivalente
- esempio
- Esempi
- eseguire
- esecuzione
- costoso
- competenza
- espressione
- più veloce
- pochi
- Compila il
- sottile
- Nome
- primi passi
- i seguenti
- Nel
- da
- function
- funzionalità
- funzioni
- generato
- ottenere
- Dare
- buono
- maggiore
- guida
- Guide
- maniglia
- Avere
- sentito
- Aiuto
- utile
- aiuta
- suo
- qui
- speranza
- Come
- Tutorial
- Tuttavia
- HTML
- HTTPS
- i
- idea
- identificare
- if
- importare
- competenze
- in
- includere
- Compreso
- Index
- India
- interno
- interesse
- interessato
- Interfaccia
- intersezione
- IT
- KDnuggets
- conoscenze
- Lingua
- grandi
- IMPARARE
- apprendimento
- meno
- Biblioteca
- probabile
- piace
- linea
- Lista
- Lunghi
- Guarda
- Principale
- make
- direttore
- molti
- matematica
- Maggio..
- misurare
- misurato
- menzione
- metodo
- metodi
- forza
- ordine
- modulo
- moduli
- Scopri di più
- Detto
- Naturale
- Linguaggio naturale
- Elaborazione del linguaggio naturale
- necessaria
- di applicazione
- mai
- Avviso..
- adesso
- numero
- numeri
- oggetto
- ottenendo
- of
- Offerte
- di frequente
- on
- una volta
- ONE
- esclusivamente
- Opinione
- Opportunità
- ottimizzazione
- Opzione
- or
- Altro
- nostro
- su
- produzione
- Packages
- parte
- per
- pezzi
- Platone
- Platone Data Intelligence
- PlatoneDati
- pratica
- presenti
- stampe
- processi
- lavorazione
- Profilo
- profiling
- Programmazione
- progetti
- fornire
- Python
- qualità
- citare
- gamma
- raggiungere
- Lettura
- si riferisce
- ricorda
- ripetere
- sostituito
- necessario
- risorsa
- Risultati
- ritorno
- problemi
- radice
- Correre
- running
- corre
- s
- Scienze
- copione
- script
- secondo
- sezioni
- vedere
- sembra
- visto
- set
- Set
- flessibile.
- compartecipazione
- lei
- Corti
- dovrebbero
- mostrato
- Un'espansione
- rallentare
- piccole
- So
- Software
- specificato
- Standard
- iniziato
- dichiarazione
- statistica
- Passi
- adatto
- Super
- sintassi
- T1
- Fai
- prende
- Target
- demolire
- Consulenza
- di
- che
- Il
- Li
- poi
- Là.
- di parti terze standard
- questo
- tre
- Attraverso
- tempo
- Timed
- volte
- a
- pure
- Totale
- esercitazioni
- Ubuntu
- us
- uso
- utilizzato
- usa
- utilizzando
- APPREZZIAMO
- Valori
- we
- quando
- while
- di chi
- volere
- con
- lavoro
- lavori
- scrittore
- scrittura
- Tu
- Trasferimento da aeroporto a Sharm
- zefiro