Python中如何同时将Flask的输出打印到控制台和日志文件?

8
我正在使用 Python 3.7.3 版本,Flask 版本为 1.0.2。
如果没有以下导入语句运行我的 app.py 文件:
import logging
logging.basicConfig(filename='api.log',level=logging.DEBUG)

Flask将在控制台显示相关的调试信息,例如POST/GET请求以及它们来自哪个IP地址。

一旦启用DEBUG日志记录,我就不再收到这些输出。我尝试在调试模式下运行我的应用程序:

app.run(host='0.0.0.0', port=80, debug=True)

但这样会产生相同的结果。有没有办法同时启用控制台输出和 Python 日志记录?这可能听起来像一个愚蠢的请求,但我想在演示目的上使用控制台,同时保留日志文件以进行故障排除。

2个回答

13

找到一个解决方案:

import logging
from flask import Flask

app = Flask(__name__)

logger = logging.getLogger('werkzeug') # grabs underlying WSGI logger
handler = logging.FileHandler('test.log') # creates handler for the log file
logger.addHandler(handler) # adds handler to the werkzeug WSGI logger

@app.route("/")
def index():
    logger.info("Here's some info")
    return "Hello World"

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=80)

其他示例:

# logs to console, and log file
logger.info("Some text for console and log file")

# prints exception, and logs to file
except Exception as ue:
        logger.error("Unexpected Error: malformed JSON in POST request, check key/value pair at: ")
        logger.error(ue)

来源: https://docstrings.wordpress.com/2014/04/19/flask-access-log-write-requests-to-file/

如果链接失效:

你可能会感到困惑,因为将处理程序添加到Flask的app.logger中并不能捕获你在控制台中看到的输出,例如:

127.0.0.1 - - [19/Apr/2014 18:51:26] "GET / HTTP/1.1" 200 -

这是因为app.logger是针对Flask的,而那些输出来自于底层WSGI模块Werkzeug。

要访问Werkzeug的记录器,我们必须调用logging.getLogger()并给它Werkzeug使用的名称。这允许我们使用以下内容记录请求到访问日志:

logger = logging.getLogger('werkzeug')
handler = logging.FileHandler('access.log')
logger.addHandler(handler)

# Also add the handler to Flask's logger for cases
#  where Werkzeug isn't used as the underlying WSGI server.
#  This wasn't required in my case, but can be uncommented as needed
#  app.logger.addHandler(handler) 

当然,您可以添加自己的格式和其他处理程序。


1
哇!你节省了我很多时间,非常感谢你。有关werkzeug的那部分非常有帮助! - QtRoS
1
太棒了!关于werkzeug的信息真是一个隐藏的宝藏。 - VITTHAL BHANDARI

9

Flask内置了一个日志记录器,可以使用app.logger访问。它只是标准库logging.Logger类的一个实例,这意味着你可以像使用基本日志记录器一样使用它。相关文档在此处

要使内置的日志记录器写入文件,您需要向日志记录器添加logging.FileHandler。在app.run中设置debug=True启动开发服务器,但不会将日志级别更改为调试级别。因此,您需要手动将日志级别设置为logging.DEBUG

示例:

import logging
from flask import Flask

app = Flask(__name__)

handler = logging.FileHandler("test.log")  # Create the file logger
app.logger.addHandler(handler)             # Add it to the built-in logger
app.logger.setLevel(logging.DEBUG)         # Set the log level to debug

@app.route("/")
def index():
    app.logger.error("Something has gone very wrong")
    app.logger.warning("You've been warned")
    app.logger.info("Here's some info")
    app.logger.debug("Meaningless debug information")
    return "Hello World"

app.run(host="127.0.0.1", port=8080)

如果您查看日志文件,它应该会将所有4行打印出来,并且控制台也会有这些行。

我将我的代码从使用 logging.basicConfig() 重构为您的建议。IP /日期 / HTTP 请求信息已返回到控制台(好耶!),但是被记录的唯一信息是传递到 app.logger.error / warning / info / debug 函数的文本。是否有一种方法也将 HTTP 调用记录到日志文件中? - rjkunde
我正在查看您提供的文档中的“注入请求信息”部分。这可能会解决这个问题。 - rjkunde
1
不好意思,不行。虽然请求信息已经正确地发布到控制台,但它被省略在日志中。请参见我上面的答案。事实证明,您需要允许WSGI底层记录器访问日志文件,这样就可以同时实现控制台发布和日志文件条目。 - rjkunde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接