好的,这是我设置所有内容的代码:
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')
会发生什么
我完全离开这里或者发生了什么事?
答案 0 :(得分:75)
为什么不这样做:
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")
如果您现在启动应用程序,您将看到error.log包含:
INFO:werkzeug: * Running on http://0.0.0.0:5000/
有关详细信息,请访问http://docs.python.org/2/howto/logging.html
好的,因为你坚持认为你不能用我向你展示的方法使用两个处理程序,我将添加一个使这一点非常清楚的例子。首先,将此日志记录代码添加到main:
import logging, logging.config, yaml
logging.config.dictConfig(yaml.load(open('logging.conf')))
现在还添加一些调试代码,以便我们看到我们的设置有效:
logfile = logging.getLogger('file')
logconsole = logging.getLogger('console')
logfile.debug("Debug FILE")
logconsole.debug("Debug CONSOLE")
剩下的就是“logging.conf”程序。让我们用它:
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]
此配置比需要的更复杂,但它还显示了日志记录模块的一些功能。
现在,当我们运行我们的应用程序时,我们会看到此输出(werkzeug-和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/
另请注意,使用了带有“HI”的自定义格式化程序。
现在查看“errors.log”文件。它包含:
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/
答案 1 :(得分:13)
好吧,我的失败源于两个误解:
1)Flask显然会忽略所有自定义日志记录,除非它在生产模式下运行
2)debug = False不足以让它在生产模式下运行。您必须将应用程序包装在任何类型的WSGI服务器中才能执行此操作
从gevent的WSGI服务器启动应用程序(并将日志记录初始化移动到更合适的位置)后,一切似乎都正常工作
答案 2 :(得分:9)
您在应用控制台中看到的输出来自底层的Werkzeug记录器,可以通过logging.getLogger('werkzeug')访问。
您的日志记录也可以在开发和发布中运行,还可以为该记录器和Flask添加处理程序。
更多信息和示例代码:Write Flask Requests to an Access Log。
答案 3 :(得分:3)
我不喜欢其他的答案,所以我坚持下去,看起来我必须在Flask完成它自己的设置之后制作我的日志配置。
@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)
我的应用程序的结构类似于
/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
答案 4 :(得分:3)
为什么不深入研究代码,看看......
我们登陆的模块是flask.logging.py
,它定义了一个名为create_logger(app)
的函数。在解决Flask的日志记录问题时,检查该功能将为潜在的罪魁祸首提供一些线索。
flask.logging.py
模块从那时起发生了很大的变化。答案仍然有助于对python日志记录提出一些一般性的警告和建议,但请注意,Flask在这方面的一些特性已在版本1中得到解决,可能不再适用。该函数中第一个可能的冲突原因是这一行:
logger = getLogger(app.logger_name)
让我们看看原因:
变量app.logger_name
在Flask.__init__()
方法中设置为import_name
的值,Flask(__name__)
本身就是app.logger_name
的接收参数。这是__name__
被赋予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)
的值,这可能是您的主要包裹的名称,在这个例子中,我们称之为“awesomeapp&#39;。” p>
现在,假设您决定手动配置和创建自己的记录器。您认为如果您的项目被命名为&#34; awesomeapp&#34;您也可以使用该名称来配置您的记录器,我认为这很可能。
Flask.logger
这样做是有意义的......除了一些问题。
第一次调用flask.logging.create_logger()
属性时,它将依次调用函数logger = getLogger(app.logger_name)
,然后将执行以下操作:
app.logger_name
还记得你在项目后如何命名你的记录器以及logging.getLogger()
如何分享这个名字?在上面的代码行中发生的是,函数del logger.handlers[:]
现在已经检索到您之前创建的记录器,并且以下说明将以一种让您稍后搔痒的方式将其弄乱。例如
logging.StreamHandler
噗,您刚丢失了之前在记录器中注册过的所有处理程序。
在函数中发生的其他事情,没有太多细节。它创建并注册两个可以向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)
个对象。一个用于日志级别&#39; debug&#39;另一个用于生产&#39;。
my_logger = getLogger('awesomeapp_logger')
有了上述细节,当Flask参与其中时,为什么我们的手动配置的记录器和处理程序行为异常会更清楚。新信息为我们提供了新的选择。如果您仍想保留单独的处理程序,最简单的方法是将记录器命名为与项目不同的名称(例如logging.FileHandler
)。如果您希望与Flask中的日志记录协议保持一致,另一种方法是使用与Flask类似的方法在Flask.logger
上注册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')
对象。
/*
* this is used to perturb given vector 'direction' by changing it by angle not more than 'angle' vector from
* base direction. Used to provide errors for player playing algorithms
*
*/
Vector3 perturbDirection( Vector3 direction, float angle ) {
// division by zero protection
if( Mathf.Approximately( direction.z, 0f )) {
direction.z = 0.0001f;
}
// 1 get some orthogonal vector to direction ( solve direction and orthogonal dot product = 0, assume x = 1, y = 1, then z = as below ))
Vector3 orthogonal = new Vector3( 1f, 1f, - ( direction.x + direction.y ) / direction.z );
// 2 get random vector from circle on flat orthogonal to direction vector. get full range to assume all cone space randomization (-180, 180 )
float orthoAngle = UnityEngine.Random.Range( -180f, 180f );
Quaternion rotateTowardsDirection = Quaternion.AngleAxis( orthoAngle, direction );
Vector3 randomOrtho = rotateTowardsDirection * orthogonal;
// 3 rotate direction towards random orthogonal vector by vector from our available range
float perturbAngle = UnityEngine.Random.Range( 0f, angle ); // range from (0, angle), full cone cover guarantees previous (-180,180) range
Quaternion rotateDirection = Quaternion.AngleAxis( perturbAngle, randomOrtho );
Vector3 perturbedDirection = rotateDirection * direction;
return perturbedDirection;
}
答案 5 :(得分:2)
这有效:
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)
答案 6 :(得分:0)
-此代码不适用于一个类/或导入中的多个日志文件
import logging
import os # for Cwd path
path = os.getcwd()
logFormatStr = '%(asctime)s %(levelname)s - %(message)s'
logging.basicConfig(filename=path + '\logOne.log', format=logFormatStr, level=logging.DEBUG), logging.info('default message')
使用logging.getLogger()方法创建日志记录实例---
使用名称或Hardcore_String创建新的记录器实例 ----首选(名称),它将在调用时指定确切的类
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
日志类型-信息,调试,错误,严重,警告
调试 ----详细信息,通常仅在诊断问题时才有用。
INFO ----确认一切正常。
警告 ----表明发生了意外情况,或在不久的将来出现了某些问题(例如“磁盘空间不足”)。该软件仍按预期运行。
错误 ----由于存在更严重的问题,该软件无法执行某些功能。
CRITICAL ----严重错误,表明程序本身可能无法继续运行。
创建新格式器
format = logging.Formatter('%(asctime)s %(levelname)s - %(message)s')
创建新文件处理程序
file_handel = logging.FileHandler(path + '\logTwo.log')
将格式设置为FileHandler并将file_handler添加到日志记录实例[logger]
file_handel.setFormatter(format)
logger.addHandler(file_handel)
向具有单独设置级别的logOne.log文件和logTwo.log添加消息
logger.info("message for logOne")
logging.debug(" message for logTwo")