2015-06-26 9 views
9

W projekcie Pythona z wieloma wątkami moje logowanie działa również do zapisu w pliku rejestratora. Zasadniczo oparty na Logging, StreamHandler and standard streamsPython butelka zawsze loguje się do konsoli, bez logowania do pliku

Częścią mojego projektu jest serwer internetowy z butelkami, który działa również dobrze. Ale każde wezwanie butelka pisze dziennik konsoli tak:

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

Jak obsługiwać ten sam sposób jak w przypadku innych kodów, więc dzienniki butelki iść także do pliku rejestratora?

+0

Zaakceptowałeś odpowiedź ayb, ale rozważ zmianę tego. Nie musisz akceptować moich (chyba że uważasz, że jest to najlepsza poprawna odpowiedź), ale wolałbym, aby przyszli użytkownicy tego pytania nie byli wprowadzani w błąd przez kod ayb, który nie powinien być używany, z wyjątkiem najlżejszych aplikacji (i nawet wtedy , jest to wątpliwa praktyka). –

Odpowiedz

3

Jeśli toczenia własne rozwiązanie, należy napisać prosty Bottle plugin, który emituje wiersze dziennika do logging rejestratorze. Oto przykład, który ustawia podstawowy rejestrator, definiuje wtyczkę do logowania i tworzy aplikację Bottle z tą wtyczką zainstalowaną na wszystkich trasach.

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) 

Uruchomienie tego kodu daje to, co chcesz:

% 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

Testowany, działa! Przechodzę, aby dodać pewne instrukcje, aby normalny "wydruk" był rejestrowany również w pliku. – gNeandr

+0

Zadowolenie pomogło! –

+0

Czy usunąłeś "wydruk", który dodałem? Próbuję użyć twojego rozwiązania z uruchomieniem programu butelkowego na wątku ... zamierzam opublikować go poniżej – gNeandr

-2

Uruchamiasz wbudowany serwer, prawda? Następnie można zrobić prosty 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) 

Lub spróbuj this one

+0

Tak, to działa. Ale widzę konflikt, ponieważ sposób, w jaki to rozwiązanie zapisuje do dziennika, zapisywałby ten sam plik dziennika, co w głównej części projektu (patrz odnośnik powyżej). Projekt butelki rozpoczyna się na jednym z wątków i myślę, że "dzienniki butelek" powinny być również obsługiwane przez główną część projektu. – gNeandr

+1

OSTRZEŻENIE: nie rób tego, chyba że NAPRAWDĘ nie przejmujesz się wydajnością. Ten kod otwiera plik na * każdym * pojedynczym żądaniu, co jest okropnym pomysłem. –

+0

Tak, to nie chodzi o perfomance, to tylko koncepcja – ayb

0

próbuję wykorzystywać rozwiązania Rona z uruchomieniem programu butelka na wątku:

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

z

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

ale to się nie powiedzie. Dowolny "print" trafia do pliku, ale nie "wydajność" (patrz wyżej), przechodzi do konsoli.

Również zmiana "debug = True" na "quiet = True" zmienia się tylko na: w ogóle nie ma wyjścia na konsoli.

+0

@Ron Każdy pomysł, który uniemożliwia wyprowadzenie "yield" do pliku logu? – gNeandr

+0

O jakiej wydajności mówisz? Nigdzie nie widzę dochodu. –

+0

Upps, zobacz komentarz "Uruchomienie tego kodu daje to, co chcesz" powyżej ... część z tego opublikowałeś "127.0.0.1 2015-06-27 16: 57: 09.983249 GET http: // localhost: 8080/200 OK "... i tego właśnie brakuje mi przy rozpoczynaniu butelki w wątku .. zobacz moją odpowiedź powyżej. – gNeandr

Powiązane problemy