6.28 logging -- Servizio di logging per Python

Nuovo nella versione 2.3. Questo modulo definisce le funzioni e le classi che implementano un sistema di logging flessibile per gli errori nelle applicazioni.

Il logging viene effettuato tramite la chiamata di metodi sulle istanze della classe Logger (da qui in poi chiamati logger). Ciascuna delle istanze ha un nome, e vengono concettualmente organizzata in uno spazio dei nomi gerarchizzato, attraverso l'uso dei punti (dots) come separatori. Per esempio, un logger chiamato "scan" è il padre dei logger "scan.text", "scan.html" e "scan.pdf". I logger possono assumere qualsiasi nome si voglia, e indicano l'area di una applicazione nella quale il messaggio di log viene generato.

I messaggi di log hanno anche un livello di importanza associato ad essi. I livelli predefiniti forniti sono DEBUG, INFO, WARNING, ERROR e CRITICAL. Per convenienza, viene indicata l'importanza di un messaggio registrato sui log chiamando un metodo appropriato di Logger. I metodi sono debug(), info(), warning(), error() e critical(), che duplicano i livelli predefiniti. Non siete costretti ad usare questi livelli: potete specificarne di propri ed usare il metodo più generale Logger, log(), che prende un esplicito argomento di livello.

I livelli possono anche essere associati ai logger, essendo impostabili sia direttamente dal programmatore, che attraverso il caricamento di una configurazione di preimpostata. Quando un metodo di logging viene chiamato su di un logger, il logger confronta il proprio livello con quello associato alla chiamata di metodo. Se il livello del logger è più alto di quello della chiamata di metodo, non viene generato nessun messaggio di log. Questo è il meccanismo di base che controlla la prolissità dei messaggi di log generati.

I messaggi di logging vengono codificati come istanze della classe LogRecord. Quando un logger decide di registrare un evento, un'istanza LogRecord viene creata dal messaggio di logging.

I messaggi di logging sono soggetti ad un meccanismo di spedizione specifico attraverso l'uso degli handlers (NdT: gestori), che sono istanze di classi derivate della classe Handler. Gli handler hanno la responsabilità di garantire che i messaggi di log (nella forma LogRecord) vengano posizionati in una locazione (o insieme di locazioni) definita e comoda per gli utenti a cui sono destinati (come un utente finale, lo staff di supporto tecnico, l'amministratore di sistema, gli sviluppatori). Agli Handler vengono passate delle istanze LogRecord, intese per particolari destinazioni. Ogni logger può avere zero, uno o più handler associati ad esso (attraverso il metodo addHandler() di Logger). In aggiunta ad ogni handler associato ad un Logger, tutti gli handler associati con tutti i predecessori del logger vengono chiamati a consegnare il messaggio.

Come per i logger, anche gli handler possono acere dei livelli associati. Un livello di handler si comporta come un filtro, nello stesso modo di un livello di un logger. Se un handler decide di consegnare un evento, viene utilizzato il metodo emit() per inviare il messaggio alla sua destinazione. La maggior parte delle classi derivate di Handler definite dall'utente avranno la necessità di sovrascrivere questo emit().

In aggiunta alla classe base Handler, vengono fornite molte utili classi derivate:

  1. Le istanze StreamHandler inviano i messaggi di errore agli stream (oggetti simil-file).

  2. Le istanze FileHandler inviano i messaggi di errori a file su disco.

  3. Le istanze RotatingFileHandler inviano i messaggi di errore ai file su disco, con il supporto alla massima dimensione del file di log e di rotazione dei file di log stessi.

  4. Le istanze SocketHandler inviano i messaggi di errore su socket TCP/IP.

  5. Le istanze DatagramHandler inviano i messaggi di errore a socket UDP.

  6. Le istanze SMTPHandler inviano i messaggi di errore a un indirizzo email predefinito.

  7. Le istanze SysLogHandler inviano i messaggi di errore al demone syslog di Unix, possibilmente su una macchina remota.

  8. Le istanze NTEventLogHandler inviano i messaggi di errore al log eventi di Windows NT/2000/XP.

  9. Le istanze MemoryHandler inviano messaggi di errore ad un buffer in memoria, che viene svuotato non appena incontrano uno specifico criterio.

  10. Le istanze HTTPHandler inviano i messaggi di errore a un server HTTP usando sia la semantica "GET" che "POST".

Sia le classi StreamHandler che FileHandler vengono definite nella porzione prinicipale del package logging. Gli altri handler vengono definiti in un modulo derivato, logging.handlers. (Esiste anche un altro modulo derivato, logging.config, per funzionalità di configurazione).

I messaggi registrati nei log vengono formattatti per la presentazione attraverso istanze della classe Formatter. Vengono inizializzati con una stringa di formattazione in grado di essere usata con l'operatore % ed un dizionario.

Per la formattazione di messaggi multipli in un batch, possono venire utilizzate istanze di BufferingFormatter. In aggiunta alla stringa di formattazione (che viene applicata ad ogni messaggio nel batch), esiste una riserva di stringhe di formato per intestazioni e pié di pagina.

Quando il filtraggio basato sui livelli di logger o sui livelli di handler non è sufficiente, possono venire aggiunte istanze di Filter, sia alle istanze di Logger che a quelle di Handler (tramite i loro metodi addFilter()). Prima di decidere di elaborare ulteriormente un messaggio, sia i logger che gli handler consultano tutti i loro filtri sui permessi. Se ogni qualche restituisce un valore falso, il messaggio non viene ulteriormente elaborato.

La funzionalità base di Filter consente di filtrare attraverso uno specifico nome di logger. Se questa funzionalità viene utilizzata, solo i messaggi inviati al logger indicato, ed ai suoi figli, vengono autorizzati a passare attraverso i filtri, tutti gli altri vengono scartati.

In aggiunta alle classi descritte precedentemente, esistono anche un certo numero di funzioni a livello di modulo.

getLogger( [name])
Restituisce un logger con lo specifico nome o, se nessun nome viene specificato, restituisce un logger che è il logger principale della gerarchia.

Tutte le chiamate a questa funzione con un dato name, restituiscono la stessa istanza di logger. Questo significa che l'istanza di logger non ha mai bisogno di essere passsata attraverso parti differenti di un'applicazione.

debug( msg[, *args[, **kwargs]])
Registra un messaggio con il livello DEBUG nel logger principale. Il messaggio msg è la stringa di formato del messaggio, e gli argomenti args sono quelli che vengono inseriti nel messaggio. L'unico argomento chiave in kwargs, che viene controllato, è exc_info()) che, se non viene valutato come falso, provoca la stampa di informazioni su un'eccezione (attraverso una chiamata a sys.exc_info()) che verranno aggiunte al messaggio di log.

info( msg[, *args[, **kwargs]])
Registra un messaggio con livello INFO nel log principale. Gli argomenti vengono interpretati come nel caso di debug().

warning( msg[, *args[, **kwargs]])
Registra un messaggio con livello WARNING nel logger principale. Gli argomenti vengono interpretati come nel caso di debug().

error( msg[, *args[, **kwargs]])
Registra un messaggio con livello ERROR nel log principale. Gli argomenti vengono interpretati come nel caso di debug().

critical( msg[, *args[, **kwargs]])
Registra un messaggio con livello CRITICAL nel log principale. Gli argomenti vengono interpretati come nel caso di debug().

exception( msg[, *args])
Registra un messaggio con livello ERROR nel log principale. Gli argomenti vengono interpretati come nel caso di debug(). Informazioni sull'eccezione verranno aggiunte al messaggio di log. Questa funzione deve essere chiamata solo da un handler dell'eccezione.

disable( lvl)
Fornisce un livello di sovrascrittura lvl per tutti i logger che ottengono la precedenza rispetto ai logger del proprio livello. Questa funzione torna utile quando si presenta la necessità di fermare temporaneamente l'emissione di log per l'intera applicazione.

addLevelName( lvl, levelName)
Associa il livello lvl con il testo levelName in un dizionario interno, che viene utilizzato per mappare i livelli numerici con una rappresentazione testuale, per esempio quando un Formatter formatta un messaggio. Questa funzione può essere usata anche per definire propri livelli. Gli unici obblighi sono che tutti i livelli usati devono essere registrati usando questa funzione, i livelli dovrebbero essere interi positivi crescenti all'aumentare dell'ordine di accuratezza.

getLevelName( lvl)
Restituisce la rappresentazione testuale del livello di logging lvl. Se il livello è uno tra quelli predefiniti, CRITICAL, ERROR, WARNING, INFO o DEBUG, otterrete la stringa corrispondente. Se sono stati associati dei livelli utilizzando addLevelName(), allora vengono restituiti i nomi associati a lvl. Altrimenti vengono restituite le stringhe "Level %s" % lvl.

makeLogRecord( attrdict)
Crea e restituisce una nuova istanza LogRecord i cui attributi sono definiti da attrdict. Questa funzione è utile per prelevare un dizionario di attributi LogRecord serializzato, inviato attraverso un socket, e ricostruito come istanza LogRecord alla fine della ricezione.

basicConfig( )
Esegue la configurazione di base per il sistema di logging creando uno StreamHandler con un Formatter predefinito e aggiungendolo al logger principale. Le funzioni debug(), info(), warning(), error() e critical() chiameranno basicConfig() automaticamente se nessun handler viene definito per il logger principale.

shutdown( )
Comunica al sistema di logging di eseguire uno shutdown ordinato, svuotando e chiudendo tutti gli handler.

setLoggerClass( klass)
Comunica al sistema di Logging di utilizzare la classe klass mentre si istanzia un logger. La classe dovrebbe definire __init__() in modo tale che venga richiesto solamente un argomento name, e __init__() dovrebbe chiamare Logger.__init__(). Questa funzione di solito viene chiamata prima che ogni logger venga istanziato dalle applicazioni che hanno la necessità di utilizzare un proprio logger personalizzato.

Vedete anche:

PEP 282, A Logging System
La proposta che descriveva questa caratteristica per includerla nella libreria standard di Python.
Il package Python logging originale
Questo è il sorgente originale del package logging. La versione del package è disponibile da questo sito e può essere sfruttata con Python 2.1x e 2.2.x, che non includono il package logging nella libreria standard.



Subsections
Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.