2015-06-26 12 views
9

In un progetto Python con più thread, il mio logging funziona bene per scrivere su un file logger. Fondamentalmente basato su Logging, StreamHandler and standard streamsbottiglia python registra sempre su console, nessuna registrazione su file

Parte del mio progetto è un server Web di bottiglia che funziona bene anche. Ma ogni chiamata bottiglia scrive un registro per la console in questo modo:

192.168.178.20 - - [26/Jun/2015 20:22:17] "GET /edit?addJob HTTP/1.1" 200 48028 

come gestire questo allo stesso modo con l'altro codice, in modo che i registri di bottiglie vanno anche al file logger?

+0

Hai accettato la risposta di ayb, ma per favore considera di cambiarlo. Non è necessario accettare il mio (a meno che non si pensi che sia la risposta corretta migliore), ma preferirei non vedere i futuri visitatori di questa domanda essere fuorviati dal codice di ayb, che non dovrebbe essere usato se non nelle applicazioni più leggere (e anche allora , è una pratica discutibile). –

risposta

3

Se stai rotolare la vostra soluzione, si dovrebbe scrivere un semplice plugin bottiglia che emette le linee di log ad un logging logger. Ecco un esempio che imposta un logger di base, definisce il plug-in di registrazione e crea un'app Bottle con quel plug-in installato su tutte le rotte.

from bottle import Bottle, request, response 
from datetime import datetime 
from functools import wraps 
import logging 

logger = logging.getLogger('myapp') 

# set up the logger 
logger.setLevel(logging.INFO) 
file_handler = logging.FileHandler('myapp.log') 
formatter = logging.Formatter('%(msg)s') 
file_handler.setLevel(logging.DEBUG) 
file_handler.setFormatter(formatter) 
logger.addHandler(file_handler) 

def log_to_logger(fn): 
    ''' 
    Wrap a Bottle request so that a log line is emitted after it's handled. 
    (This decorator can be extended to take the desired logger as a param.) 
    ''' 
    @wraps(fn) 
    def _log_to_logger(*args, **kwargs): 
     request_time = datetime.now() 
     actual_response = fn(*args, **kwargs) 
     # modify this to log exactly what you need: 
     logger.info('%s %s %s %s %s' % (request.remote_addr, 
             request_time, 
             request.method, 
             request.url, 
             response.status)) 
     return actual_response 
    return _log_to_logger 

app = Bottle() 
app.install(log_to_logger) 

@app.route('/') 
def home(): 
    return ['hello, world'] 

app.run(host='0.0.0.0', port='8080', quiet=True) 

esecuzione che il codice cede ciò che si vuole:

% python myapp.py & 
% curl -v http://localhost:8080/ 
% tail myapp.log  
127.0.0.1 2015-06-27 16:57:09.983249 GET http://localhost:8080/ 200 OK 
+0

Testato, funziona! Aggiungendo alcune istruzioni in modo che una normale "stampa" acceda anche al file. – gNeandr

+0

Felice ha aiutato! –

+0

Hai rimosso la 'stampa' che ho aggiunto? Sto provando ad usare la tua soluzione con l'avvio del programma bottiglia su un thread ... andando a postarlo sotto – gNeandr

-2

Si esegue il server integrato giusto? Poi si può fare un semplice plugin:

from bottle import request, response, route, install, run 
from datetime import datetime 


def logger(func): 
    def wrapper(*args, **kwargs): 
     log = open('log.txt', 'a') 
     log.write('%s %s %s %s %s \n' % (request.remote_addr, datetime.now().strftime('%H:%M'), 
             request.method, request.url, response.status)) 
     log.close() 
     req = func(*args, **kwargs) 
     return req 
    return wrapper 

install(logger) 


@route('/') 
def index(): 
    return 'Hello, World' 

run(quiet=True) 

Oppure provate this one

+0

Sì, funziona. Ma vedo un conflitto perché il modo in cui questa soluzione scrive su un log dovrebbe scrivere sullo stesso file di log come con la parte principale del progetto (vedi link di riferimento sopra). Il progetto di bottiglia è avviato su uno di alcuni thread e penso che i "log delle bottiglie" dovrebbero essere gestiti anche dalla parte principale del progetto. – gNeandr

+1

ATTENZIONE: non farlo, a meno che NON VERAMENTE non ti interessi delle prestazioni. Questo codice apre un file su * ogni * singola richiesta, che è una pessima idea. –

+0

sì, non si tratta di perfomance, è solo un concetto – ayb

0

Sto cercando di usare la soluzione di Ron con l'avvio del programma di bottiglia a un filo:

tWeb = Thread(target=runWeb, args=('192.168.178.16', 5003)).start() 

con

def runWeb(aserver, aport): 
    run(host=aserver, port=aport, debug=True) 

ma questo fallisce. Qualsiasi 'stampa' va al file, ma non al 'rendimento' (vedi sopra), va alla console.

Inoltre, la modifica di "debug = True" su "quiet = True" cambia solo in: non esiste alcun output sulla console.

+0

@Ron Qualche idea su cosa impedisce di emettere il "rendimento" nel file di registro? – gNeandr

+0

Di quale rendimento stai parlando? Non vedo un rendimento da nessuna parte. –

+0

Upps, si prega di vedere il tuo commento "Esecuzione di quel codice produce quello che vuoi" sopra ... parte di esso postato "127.0.0.1 2015-06-27 16: 57: 09.983249 OTTIENI http: // localhost: 8080/200 OK "... ed è quello che mi manca quando avvii la parte della bottiglia in una discussione .. vedi la mia risposta sopra. – gNeandr