2015-06-26 7 views
9

In einem Python-Projekt mit mehreren Threads funktioniert meine Protokollierung gut, um in eine Logger-Datei zu schreiben. Basiert auf Logging, StreamHandler and standard streamsPythonflasche meldet sich immer an der Konsole an, keine Protokollierung in Datei

Teil meines Projektes ist ein Flaschenwebserver, der auch gut läuft. Aber jeder Flasche Aufruf schreibt ein Protokoll an die Konsole wie folgt aus:

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

Wie dies die gleiche Art und Weise wie bei den anderen Code zu handhaben, so dass die Flasche Protokolle gehen auch an den Logger-Datei?

+0

Sie haben die Antwort von ayb akzeptiert, aber bitte überlegen Sie, dies zu ändern. Keine Notwendigkeit, meins zu akzeptieren (es sei denn, Sie denken, es ist die beste Antwort), aber ich würde zukünftige Besucher dieser Frage lieber nicht durch den ayb-Code in die Irre führen, der nicht in den leichtesten Anwendungen (und selbst dann) verwendet werden sollte es ist eine fragwürdige Praxis). –

Antwort

3

Wenn Sie Ihre eigene Lösung sind rollen, sollten Sie eine einfache Flasche Plugin schreiben, die Protokollzeilen zu einem logging Logger emittiert. Hier ist ein Beispiel, das einen Basis-Logger einrichtet, das Logging-Plugin definiert und eine Flaschen-App erstellt, bei der das Plugin auf allen Routen installiert ist.

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) 

diesen Code Laufen bringt, was Sie wollen:

% 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

Getestet, funktioniert! Gehen Sie einige Anweisungen hinzufügen, so dass ein normaler 'print' auch in der Datei protokolliert wird. – gNeandr

+0

Glücklich es geholfen! –

+0

Haben Sie den 'Print', den ich hinzugefügt habe, entfernt? Ich versuche, Ihre Lösung mit dem Starten des Flaschenprogramms auf einem Thread ... zu verwenden, um es unter – gNeandr

-2

Sie laufen eingebauten Server richtig? Dann können Sie ein einfaches Plugin machen:

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) 

Oder versuchen this one

+0

Ja, das funktioniert. Aber ich sehe einen Konflikt, weil die Art und Weise, wie diese Lösung in ein Protokoll schreibt, in dieselbe Protokolldatei geschrieben wird wie beim Hauptteil des Projekts (siehe den Verweis oben). Das Flaschenprojekt wird auf einem von einigen Threads gestartet und ich denke, die "Flaschenprotokolle" sollten auch vom Hauptprojektteil behandelt werden. – gNeandr

+1

WARNUNG: Tun Sie dies nicht, es sei denn, Sie interessieren sich NICHT wirklich für die Leistung. Dieser Code öffnet eine Datei auf * jeder * einzelnen Anfrage, was eine schreckliche Idee ist. –

+0

yep, es geht nicht um Leistung, es ist nur ein Konzept – ayb

0

Ich versuche Rons Lösung mit dem Start der Flasche Programm auf einem Thread zu verwenden:

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

mit

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

aber das schlägt fehl. Irgendein 'print' geht zur Datei, aber nicht zum 'yield' (siehe oben), es geht zur Konsole.

Auch die Änderung von "debug = True" zu "quiet = True" ändert sich nur zu: Es gibt überhaupt keine Ausgabe auf der Konsole.

+0

@Ron Gibt es eine Idee, was die Ausgabe der "Ausbeute" in die Protokolldatei verhindert? – gNeandr

+0

Von welchem ​​Ertrag sprichst du? Ich sehe nirgends eine Rendite. –

+0

Upps, bitte beachten Sie Ihren Kommentar "Ausführen dieses Codes ergibt, was Sie wollen" oben ... Teil davon Sie gepostet "127.0.0.1 2015-06-27 16: 57: 09.983249 GET http: // localhost: 8080/200 OK "... und das ist was ich vermisse, wenn ich den Flaschenteil in einem Thread starte ... sehe meine Antwort oben. – gNeandr

Verwandte Themen