我有一个Flask应用程序,该应用程序运行良好并会偶尔出现错误,当与debug=True以下命令一起运行时可见:
debug=True
if __name__ == '__main__': app.run(debug=True)
我收到有用的错误消息,例如:
Traceback (most recent call last): File "./main.py", line 871, in index_route KeyError: 'stateIIIII'
我在生产环境中运行应用程序时(使用Lighttpd + fastcgi)将这样的错误消息保存到文件中。
寻找不同的StackOverflow问题后(http://flask.pocoo.org/docs/errorhandling/,http://docs.python.org/2/library/logging.html等); Flask邮件列表;和一些博客,似乎没有简单的方法可以将所有重大错误消息发送到文件中-我需要使用Python日志记录模块自定义内容。所以我想出了以下代码。
在我的应用程序文件的顶部,我有各种导入,然后是:
app = Flask(__name__) if app.debug is not True: import logging from logging.handlers import RotatingFileHandler file_handler = RotatingFileHandler('python.log', maxBytes=1024 * 1024 * 100, backupCount=20) file_handler.setLevel(logging.ERROR) app.logger.setLevel(logging.ERROR) app.logger.addHandler(file_handler)
然后,我将每个路由的代码放入try / except语句中,并使用traceback找出错误来自哪一行,并显示一条不错的错误消息:
def some_route(): try: # code for route in here (including a return statement) except: exc_type, exc_value, exc_traceback = sys.exc_info() app.logger.error(traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2)) return render_template('error.html')
然后在文件末尾删除该debug=True语句。虽然我认为我不需要这样做,因为当应用程序在生产环境中运行时,它是由fastcgi服务器(?)运行的。我的应用程序代码的最后两行如下所示:
if __name__ == '__main__': app.run()
我正在努力使这个工作。我认为我管理的最好的方法是使用(app.logger.error(‘test message’))将一条错误日志消息保存在文件中,但是它只会打印一条消息。直接忽略在该错误之后立即记录另一个错误的尝试。
我不知道为什么它不起作用,但是我可以说出它是怎么做的。
首先,你不需要设置app.logger的级别。因此删除此行app.logger.setLevel()。
app.logger.setLevel()
你想要保存异常并为每个视图返回错误页面。在任何地方编写此代码都是很多工作。Flask提供了一种执行此操作的方法。定义这样的错误处理程序方法。
@app.errorhandler(500) def internal_error(exception): app.logger.error(exception) return render_template('500.html'), 500
每当视图引发异常时,都会调用此方法并将异常作为参数传递。Python日志记录提供了异常方法,该方法用于保存对异常的完整追溯。
由于这可以处理所有异常,因此你甚至无需将代码放在try / except块中。但是,如果你想在调用错误处理程序之前执行某些操作(例如,回滚会话或事务),请执行以下操作:
try: #code except: #code raise
如果你希望为日志文件中的每个条目添加日期和时间,则可以使用以下代码(代替问题中提供的类似代码)。
if app.debug is not True: import logging from logging.handlers import RotatingFileHandler file_handler = RotatingFileHandler('python.log', maxBytes=1024 * 1024 * 100, backupCount=20) file_handler.setLevel(logging.ERROR) formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s") file_handler.setFormatter(formatter) app.logger.addHandler(file_handler)