tutorial sirve que para espaƱol python logging python-2.7 flask

python - sirve - Registro de Flask-No se puede hacer que escriba en un archivo



para que sirve python flask (6)

¿Por qué no hacer una inmersión en el código y ver ...

El módulo en el que aterrizamos es flask.logging.py , que define una función llamada create_logger(app) . La inspección de esa función dará algunas pistas sobre los posibles culpables al solucionar problemas de registro con Flask.

EDIT: esta respuesta fue para Flask antes de la versión 1. El módulo flask.logging.py ha cambiado considerablemente desde entonces. La respuesta aún ayuda con algunas advertencias generales y consejos sobre el registro de Python, pero tenga en cuenta que algunas de las peculiaridades de Flask en ese sentido se han abordado en la versión 1 y es posible que ya no se apliquen.

La primera causa posible de conflictos en esa función es esta línea:

logger = getLogger(app.logger_name)

Veamos por qué:

La variable app.logger_name se establece en el método Flask.__init__() en el valor de import_name , que a su vez es el parámetro de recepción de Flask(__name__) . Eso es app.logger_name se le asigna el valor de __name__ , que probablemente será el nombre de su paquete principal, vamos a llamarlo ''awesomeapp'' para este ejemplo.

Ahora, imagine que decidió configurar y configurar su propio registrador manualmente. ¿Cuál cree que es la probabilidad de que si su proyecto se llama "awesomeapp" también use ese nombre para configurar su registrador, creo que es bastante probable.

my_logger = logging.getLogger(''awesomeapp'') # doesn''t seem like a bad idea fh = logging.FileHandler(''/tmp/my_own_log.log'') my_logger.setLevel(logging.DEBUG) my_logger.addHandler(fh)

Tiene sentido hacer esto ... excepto por algunos problemas.

Cuando se invoca la propiedad Flask.logger por primera vez, a su vez llamará a la función flask.logging.create_logger() y se producirán las siguientes acciones:

logger = getLogger(app.logger_name)

¿Recuerda cómo llamó a su registrador después del proyecto y cómo app.logger_name comparte ese nombre también? Lo que sucede en la línea de código anterior es que la función logging.getLogger() ahora ha recuperado el registrador creado anteriormente y las siguientes instrucciones están a punto de meterse con ello de una manera que hará que te rasques la cabeza más tarde. Por ejemplo

del logger.handlers[:]

Poof, acabas de perder todos los manejadores que hayas registrado previamente en tu registrador.

Otras cosas que suceden dentro de la función, sin entrar demasiado en detalles. Crea y registra dos objetos logging.StreamHandler que pueden escupir a sys.stderr y / u objetos de Response . Uno para el nivel de registro ''depuración'' y otro para ''producción''.

class DebugLogger(Logger): def getEffectiveLevel(self): if self.level == 0 and app.debug: return DEBUG return Logger.getEffectiveLevel(self) class DebugHandler(StreamHandler): def emit(self, record): if app.debug and _should_log_for(app, ''debug''): StreamHandler.emit(self, record) class ProductionHandler(StreamHandler): def emit(self, record): if not app.debug and _should_log_for(app, ''production''): StreamHandler.emit(self, record) debug_handler = DebugHandler() debug_handler.setLevel(DEBUG) debug_handler.setFormatter(Formatter(DEBUG_LOG_FORMAT)) prod_handler = ProductionHandler(_proxy_stream) prod_handler.setLevel(ERROR) prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT)) logger.__class__ = DebugLogger logger.addHandler(debug_handler) logger.addHandler(prod_handler)

Con los detalles anteriores a la luz, debería quedar más claro por qué nuestros registradores y manipuladores configurados manualmente se comportan mal cuando se involucra Flask. La nueva información nos da nuevas opciones sin embargo. Si aún desea mantener manejadores separados, el enfoque más simple es nombrar su registrador a algo diferente al proyecto (por ejemplo, my_logger = getLogger(''awesomeapp_logger'') ). Otro enfoque, si desea ser coherente con los protocolos de registro en Flask, es registrar un objeto Flask.logger en Flask.logger utilizando un enfoque similar al Flask.

import logging def set_file_logging_handler(app): logging_path = app.config[''LOGGING_PATH''] class DebugFileHandler(logging.FileHandler): def emit(self, record): # if your app is configured for debugging # and the logger has been set to DEBUG level (the lowest) # push the message to the file if app.debug and app.logger.level==logging.DEBUG: super(DebugFileHandler, self).emit(record) debug_file_handler = DebugFileHandler(''/tmp/my_own_log.log'') app.logger.addHandler(debug_file_handler) app = Flask(__name__) # the config presumably has the debug settings for your app app.config.from_object(config) set_file_logging_handler(app) app.logger.info(''show me something'')

Ok, aquí está el código donde configuro todo:

if __name__ == ''__main__'': app.debug = False applogger = app.logger file_handler = FileHandler("error.log") file_handler.setLevel(logging.DEBUG) applogger.setLevel(logging.DEBUG) applogger.addHandler(file_handler) app.run(host=''0.0.0.0'')

Lo que ocurre es

  1. error.log se crea
  2. Nada está escrito en él
  3. A pesar de no agregar un StreamHandler y establecer la depuración en falso, sigo recibiendo todo en STDOUT (esto podría ser correcto, pero aún así parece extraño)

¿Estoy totalmente fuera de aquí o en lo que está sucediendo?


¿Por qué no hacerlo así?

if __name__ == ''__main__'': init_db() # or whatever you need to do import logging logging.basicConfig(filename=''error.log'',level=logging.DEBUG) app.run(host="0.0.0.0")

Si ahora inicia su aplicación, verá que error.log contiene:

INFO:werkzeug: * Running on http://0.0.0.0:5000/

Para obtener más información, visite http://docs.python.org/2/howto/logging.html

De acuerdo, como insistes en que no puedes tener dos controladores con el método que te mostré, agregaré un ejemplo que lo aclare. Primero, agrega este código de registro a tu principal:

import logging, logging.config, yaml logging.config.dictConfig(yaml.load(open(''logging.conf'')))

Ahora también agregue un código de depuración para que veamos que nuestra configuración funciona:

logfile = logging.getLogger(''file'') logconsole = logging.getLogger(''console'') logfile.debug("Debug FILE") logconsole.debug("Debug CONSOLE")

Todo lo que queda es el programa "logging.conf". Usemos eso:

version: 1 formatters: hiformat: format: ''HI %(asctime)s - %(name)s - %(levelname)s - %(message)s'' simple: format: ''%(asctime)s - %(name)s - %(levelname)s - %(message)s'' handlers: console: class: logging.StreamHandler level: DEBUG formatter: hiformat stream: ext://sys.stdout file: class: logging.FileHandler level: DEBUG formatter: simple filename: errors.log loggers: console: level: DEBUG handlers: [console] propagate: no file: level: DEBUG handlers: [file] propagate: no root: level: DEBUG handlers: [console,file]

Esta configuración es más complicada de lo necesario, pero también muestra algunas características del módulo de registro.

Ahora, cuando ejecutamos nuestra aplicación, vemos esta salida (werkzeug- y console-logger):

HI 2013-07-22 16:36:13,475 - console - DEBUG - Debug CONSOLE HI 2013-07-22 16:36:13,477 - werkzeug - INFO - * Running on http://0.0.0.0:5000/

También tenga en cuenta que se utilizó el formateador personalizado con el "HI".

Ahora mira el archivo "errors.log". Contiene:

2013-07-22 16:36:13,475 - file - DEBUG - Debug FILE 2013-07-22 16:36:13,477 - werkzeug - INFO - * Running on http://0.0.0.0:5000/


Bien, mi fracaso se originó en dos conceptos erróneos:

1) Aparentemente, Flask ignorará todo el registro personalizado a menos que se ejecute en modo de producción.

2) debug = False no es suficiente para permitir que se ejecute en modo de producción. Debe envolver la aplicación en cualquier tipo de servidor WSGI para hacerlo

Después de iniciar la aplicación desde el servidor WSGI de gevent (y mover la inicialización del registro a un lugar más apropiado) todo parece funcionar bien


El resultado que ve en la consola de su aplicación proviene del registrador Werkzeug subyacente al que se puede acceder a través de logging.getLogger (''werkzeug'').

Su registro puede funcionar tanto en el desarrollo como en el lanzamiento al agregar controladores a ese registrador, así como también al Flask.

Más información y código de ejemplo: Escribir solicitudes de frasco en un registro de acceso .


Esto funciona:

if __name__ == ''__main__'': import logging logFormatStr = ''[%(asctime)s] p%(process)s {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s'' logging.basicConfig(format = logFormatStr, filename = "global.log", level=logging.DEBUG) formatter = logging.Formatter(logFormatStr,''%m-%d %H:%M:%S'') fileHandler = logging.FileHandler("summary.log") fileHandler.setLevel(logging.DEBUG) fileHandler.setFormatter(formatter) streamHandler = logging.StreamHandler() streamHandler.setLevel(logging.DEBUG) streamHandler.setFormatter(formatter) app.logger.addHandler(fileHandler) app.logger.addHandler(streamHandler) app.logger.info("Logging is set up.") app.run(host=''0.0.0.0'', port=8000, threaded=True)


No me gustaron las otras respuestas, así que seguí y parece que tuve que hacer que mi configuración de registro AFTER Flask hiciera su propia configuración.

@app.before_first_request def initialize(): logger = logging.getLogger("your_package_name") logger.setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) formatter = logging.Formatter( """%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:/n%(message)s""" ) ch.setFormatter(formatter) logger.addHandler(ch)

Mi aplicación está estructurada como

/package_name __main__.py <- where I put my logging configuration __init__.py <- conveniance for myself, not necessary /tests /package_name <- Actual flask app __init__.py /views /static /templates /lib

Siguiendo estas instrucciones http://flask.pocoo.org/docs/0.10/patterns/packages/