coverage gunicorn <params>
non funziona, perché gunicorn crea processi di lavoro e il modulo coverage
non può funzionare su biforcazioni (fondamentalmente, creazione di nuovi processi). È possibile utilizzare the coverage API, però, ad esempio, nel modulo python che contiene l'applicazione WSGI:
# wsgi_with_coverage.py
import atexit
import sys
import coverage
cov = coverage.coverage()
cov.start()
from wsgi import application # adjust to python module containing your wsgi application
def save_coverage():
print >> sys.stderr, "saving coverage"
cov.stop()
cov.save()
atexit.register(save_coverage)
Quindi eseguire gunicorn -w 1 wsgi_with_coverage:application <other params>
.
Il problema è che le funzioni atexit
non vengono chiamate se si uccide il processo gunicorn, ad esempio tramite CTRL + C. Ma loro sono chiamato SIGHUP
, quindi se si fa kill -HUP $(cat <gunicorn_pidfile_here>)
, i dati di copertura devono essere salvati (di default su ".coverage" nella directory corrente).
Un possibile avvertimento è che questo non funzionerà con più di un addetto di gunicorn, perché sovrascriverebbero tutti il file ".coverage". Se hai assolutamente bisogno di più di un lavoratore, puoi scrivere a ".coverage-%d" % os.getpid()
(imposta il nome del file via the data_file
parameter to the coverage
constructor) e utilizzare the combine()
method per unire le singole misurazioni.
Questo dovrebbe funzionare anche su altri server WSGI, a seconda che consentano loro di pulire i processi di lavoro tramite il metodo atexit
.
Il consiglio SIGHUP non è così buono :). Gunicorn ricarica i processi di lavoro dopo aver recuperato SIGHUP. Cioè, i dati di copertura raccolti non sono esattamente salvati, ma sovrascritti con quelle cose che accadono solo a carico. L'invio di SIGTER, d'altra parte, attiva correttamente il gestore di atexit e chiude in modo pulito Gunicorn. –