Domanda

Sto cercando di scaricare un elenco di tutti i thread attivi incluso lo stack corrente di ciascuno. Posso ottenere un elenco di tutti i thread usando threading.enumerate (), ma non riesco a trovare un modo per arrivare allo stack da lì.

Sfondo: un'app Zope / Plone si spaventa di tanto in tanto, consumando il 100% della CPU e deve essere riavviata. Ho la sensazione che sia un ciclo che non termina correttamente, ma non riesco a riprodurlo nell'ambiente di test per la verifica. Sono riuscito a registrare un gestore di segnale che può essere attivato dall'esterno, quindi posso attivare un po 'di codice non appena la situazione si ripresenta. Se potessi scaricare lo stacktrace per tutti i thread attivi, questo mi darebbe un indizio su cosa vada storto. La cosa del buco gira su Python 2.4 ...

Le idee su come rintracciare situazioni come queste sono apprezzate :)

Saluti,    Chriss

È stato utile?

Soluzione

Quando si utilizza Zope, si desidera installare Products.signalstack o mr.freeze ; questi sono stati progettati proprio per questo scopo!

Invia un segnale USR1 al tuo server Zope e scaricherà immediatamente le tracce dello stack per tutti i thread sulla console. Lo farà anche se tutti i thread di Zope sono bloccati.

Questi pacchetti usano indirettamente threadframes ; per Python versione 2.5 e successive, quando non usando Zope, puoi costruire la stessa funzionalità usando sys._current_frames () per accedere ai frame dello stack per thread.

A partire da Zope 2.12.5 questa funzionalità è integrata in Zope stessa e non è più necessario installare pacchetti aggiuntivi.

Altri suggerimenti

Come indica il jitter in una risposta precedente sys._current_frames () ti dà ciò di cui hai bisogno per v2.5 +. Per i più pigri il seguente frammento di codice ha funzionato per me e può aiutarti:

print >> sys.stderr, "\n*** STACKTRACE - START ***\n"
code = []
for threadId, stack in sys._current_frames().items():
    code.append("\n# ThreadID: %s" % threadId)
    for filename, lineno, name, line in traceback.extract_stack(stack):
        code.append('File: "%s", line %d, in %s' % (filename,
                                                    lineno, name))
        if line:
            code.append("  %s" % (line.strip()))

for line in code:
    print >> sys.stderr, line
print >> sys.stderr, "\n*** STACKTRACE - END ***\n"

Per Python 3.3 e versioni successive, esiste faulthandler .dump_traceback () .

Il codice seguente produce un output simile, ma include il nome del thread e potrebbe essere migliorato per stampare più informazioni.

for th in threading.enumerate():
    print(th)
    traceback.print_stack(sys._current_frames()[th.ident])
    print()

2.4. Peccato. Da Python 2.5 in poi c'è sys._current_frames () .

Ma potresti provare threadframe . E se il makefile ti dà problemi potresti provare questo setup.py per threadframe

Output di esempio quando si utilizza il threadframe

Solo per completezza, Products.LongRequestLogger è super utile per identificare i colli di bottiglia e per fare ciò scarica stacktraces a intervalli specifici.

Esiste una ricetta applicabile su ASPN . Puoi usare threading.enumerate () per ottenere tutte le maree, quindi chiama _async_raise () con qualche eccezione adatta per forzare una traccia dello stack.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top