爲什麼不把代碼中的潛水,看到...
我們的土地上是模塊flask.logging.py
,它定義了一個名爲create_logger(app)
的函數。在解決Flask的日誌記錄問題時,檢查該功能將爲潛在的肇事者提供一些線索。
在該功能衝突的第一個可能的原因是該行:
logger = getLogger(app.logger_name)
讓我們來看看爲什麼:
變量app.logger_name
在Flask.__init__()
方法設置爲import_name
價值,這本身就是接收參數Flask(__name__)
。即app.logger_name
被分配了值__name__
,這可能是您的主包的名稱,讓我們對這個例子稱之爲'awesomeapp'。
現在,假設您決定手動配置並創建自己的記錄器。你認爲如果你的項目命名爲「awesomeapp」,你也可以用這個名字來配置你的記錄器,我認爲這很有可能。
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)
這樣做是有道理的,除了幾個問題。
當Flask.logger
屬性調用首次將依次調用函數flask.logging.create_logger()
,並執行以下操作將接踵而至:
logger = getLogger(app.logger_name)
還記得你的項目的名字命名的記錄器,以及如何app.logger_name
股份表示名字呢?在上面的代碼行中發生的是,功能logging.getLogger()
現在已經檢索到您以前創建的記錄器,並且以下說明將以一種會讓您在以後搔癢的方式混淆它。例如,
del logger.handlers[:]
噗,你剛剛失去了所有你以前可能註冊過的處理程序。
在函數內部發生的其他事情,沒有深入細節。它會創建並註冊兩個可以吐出到sys.stderr
和/或Response
對象的對象。一個用於日誌級別「調試」,另一個用於「生產」。
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)
對於上述細節,以點燃它應該變得更加清晰,爲什麼我們的手動配置的記錄似乎在瓶介入到不正常的行爲。新的信息爲我們提供了新的選擇。如果您仍想保留單獨的記錄器,最簡單的方法是將其命名爲與項目不同的項目(例如my_logger = getLogger('awesomeapp_logger')
)。如果你想與Flask中的日誌協議保持一致,另一個選擇是使用類似於Flask的方法在Flask.logger
上註冊一個logging.FileHandler
對象。
def enable_file_logging(app):
import logging
from flask.logging import _should_log_for
logging_path = app.config['LOGGING_PATH']
class DebugFileHandler(logging.FileHandler):
def emit(self, record):
if app.debug and _should_log_for(app, 'debug'):
logging.FileHandler.emit(self, record)
debug_file_handler = DebugFileHandler('/tmp/my_own_log.log')
app.logger.addHandler(debug_file_handler)
app = Flask(__name__)
enable_file_logging(app)
當你設置'app.debug = True'時會發生什麼? – dAnjou
沒有什麼變化 – fleshgolem