- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在尝试将来自一个非常简单的 flask 应用程序的应用程序日志消息保存在日志文件中。虽然当我使用嵌入式 Flask 服务器运行应用程序时这可以完美运行,但在 gUnicorn 中运行时它根本不工作,基本上,无论是日志文件(我的 Flask 应用程序中指定的文件)还是重定向,都不会重定向应用程序输出运行 gunicorn 时的 STDOUT。
也就是说,这是我的 Flask 应用:
@app.route('/')
def index():
app.logger.debug('Into /!!!!')
print 'Will this print?'
return 'Flask is running!'
if __name__ == '__main__':
#Setup the logger
file_handler = FileHandler('test.log')
handler = logging.StreamHandler()
file_handler.setLevel(logging.DEBUG)
handler.setLevel(logging.DEBUG)
file_handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'))
app.logger.addHandler(handler)
app.logger.addHandler(file_handler)
app.run(debug=True)
现在,如果我以以下方式启动应用程序:
python app.py
我得到了预期的输出:
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
--------------------------------------------------------------------------------
DEBUG in app [app.py:23]:
Into /!!!!
--------------------------------------------------------------------------------
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]
Will this print?
127.0.0.1 - - [11/Mar/2015 09:36:18] "GET / HTTP/1.1" 200 -
拖尾test.log,我明白了:
2015-03-11 09:36:18,375 DEBUG: Into /!!!! [in app.py:23]
到目前为止一切看起来都很棒,然后当我尝试使用 nginx + gunicorn 运行应用程序时,首先我尝试像这样运行 gunicorn:
gunicorn app:app -b localhost:8000 --debug --log-level debug
如果我转到 http://localhost,应用程序正在运行:
curl http://localhost
Flask is running!
但是查看日志文件,是空的,没有写入任何内容。我添加了 777 权限只是为了检查它是否是权限问题无济于事。然后查看 gunicorn 标准输出,除了 print 语句之外什么都没有写:
2015-03-11 09:42:06 [25641] [DEBUG] GET /
Will this print?
Looking around ,我尝试将所有输出重定向到 gunicorn 日志,然后像这样启动 gunicorn:
gunicorn app:app -b localhost:8000 --debug --log-file /tmp/test.log --log-level debug --error-logfile /tmp/error.log
但现在我什至没有在 gunicorn 文件中获得打印语句,这是 test.log 和 error.log 的输出(它们是相同的):
2015-03-11 09:46:17 [26257] [DEBUG] tmp_upload_dir: None
2015-03-11 09:46:17 [26257] [DEBUG] keyfile: None
2015-03-11 09:46:17 [26257] [DEBUG] backlog: 2048
2015-03-11 09:46:17 [26257] [DEBUG] logger_class: simple
2015-03-11 09:46:17 [26257] [INFO] Starting gunicorn 17.5
2015-03-11 09:46:17 [26257] [DEBUG] Arbiter booted
2015-03-11 09:46:17 [26257] [INFO] Listening at: http://127.0.0.1:8000 (26257)
2015-03-11 09:46:17 [26257] [INFO] Using worker: sync
2015-03-11 09:46:17 [26262] [INFO] Booting worker with pid: 26262
2015-03-11 09:48:15 [26262] [DEBUG] GET /
有一个非常相似的问题here ,其中一个答案似乎表明在 gunicorn 中运行时没有可用的应用程序记录器???这听起来,至少,很奇怪......那我应该如何登录?
另一个 proposed solution似乎建议不要使用 Flask 记录器,但与 gunicorn 无关(我认为)......
我错过了什么?我应该放弃 gunicorn 并选择 Apache-mod wsgi 吗? Nginx-uWSGI?快速CGI?有什么想法吗?
谢谢!亚历杭德罗
编辑:
我已经尝试使用 uWGSI 而不是 gunicorn 和相同的行为进行相同的设置,但没有获得任何应用程序日志记录。
现在基于 this response这个other one ,我想出了这个(在 gUnicorn 和 uWSGI 上,两者都有效)
from flask import Flask
import logging
from logging import Formatter, FileHandler
app = Flask(__name__)
LOGGER = logging.getLogger('whatever')
file_handler = FileHandler('test.log')
handler = logging.StreamHandler()
file_handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
handler.setFormatter(Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]'
))
LOGGER.addHandler(file_handler)
LOGGER.addHandler(handler)
LOGGER.setLevel(logging.INFO)
@app.route('/')
def hello():
LOGGER.info('info log')
LOGGER.debug('debug log')
return 'Hello!'
if __name__ == '__main__':
app.run()
gunicorn 的输出:
2015-03-11 12:25:01 [11540] [INFO] Starting gunicorn 17.5
2015-03-11 12:25:01 [11540] [INFO] Listening at: http://127.0.0.1:8000 (11540)
2015-03-11 12:25:01 [11540] [INFO] Using worker: sync
2015-03-11 12:25:01 [11545] [INFO] Booting worker with pid: 11545
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24]
然后查看我的 test.log 文件:
2015-03-11 12:26:20,765 INFO: info log [in /home/mosquito/www/flask-project/flask-project/app.py:24]
所以是的,它有点工作,但原来的问题仍然存在......为什么 Flask 记录器在 wsgi 容器中运行时似乎不起作用 - gunicorn,uWSGI?
最佳答案
您自己在这里回答了您的问题。虽然我会添加我的答案,希望它可以帮助其他有类似问题的人。
由于您的问题有 2 个部分,其中第一部分已解决,因此请标记我对每个部分的回答:
第 1 部分:如果不是直接通过 python 运行应用程序,而是在 gunicorn 下运行它,则不会发生日志记录这是因为,当直接运行时,name == 'main' 为 True,并且您的代码同时初始化了 FileHandler 和 StreamHandler,并且日志记录工作正常。但是当通过 gunicorn 运行时,name == 'main' 会失败,因为 name 将包含您的模块的名称。这意味着不会初始化任何有效处理程序。因此看不到任何日志记录。
第 2 部分:为什么 Flask 记录器在 gunicorn/uWSGI 下默认不工作最新的 flask 版本从头开始初始化 app.logger,并在默认情况下附加一些处理程序,如 DebugHandler、StreamHandler,具体取决于 app.debug==True。记录器仍然不够,只会记录到 STDERR。在过去的几个版本中,gunicorn 发生了多次变化。版本 19.4.1 不会将 STDOUT 和 STDERR 捕获到 gunicorn error.log。但它确实提供了名称为“gunicorn”、“gunicorn.access”和“gunicorn.error”的记录器。最后一个有一个 FileHandler 写入配置的 error.log。如果您希望 flask 应用程序中的日志转到 error.log,请使用以下方法之一:方法1:
#only use gunicorn.error logger for all logging
LOGGER = logging.getLogger('gunicorn.error')
LOGGER.info('my info')
LOGGER.debug('debug message')
# this would write the log messages to error.log
方法2:
# Only use the FileHandler from gunicorn.error logger
gunicorn_error_handlers = logging.getLogger('gunicorn.error').handlers
app.logger.handlers.extend(gunicorn_error_handlers )
app.logger.addHandler(myhandler1)
app.logger.addHandler(myhandler2)
app.logger.info('my info')
app.logger.debug('debug message')
将推荐方法 2,因为除了 gunicorn.error 之外,您还可以保留任何您想要的处理程序。此外,您可以根据条件选择不添加 gunicorn.error 处理程序。
谢谢
关于python - 在 gunicorn 中运行时,Flask 应用程序记录器无法正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28982106/
我是 C 语言新手,我编写了这个 C 程序,让用户输入一年中的某一天,作为返回,程序将输出月份以及该月的哪一天。该程序运行良好,但我现在想简化该程序。我知道我需要一个循环,但我不知道如何去做。这是程序
我一直在努力找出我的代码有什么问题。这个想法是创建一个小的画图程序,并有红色、绿色、蓝色和清除按钮。我有我能想到的一切让它工作,但无法弄清楚代码有什么问题。程序打开,然后立即关闭。 import ja
我想安装screen,但是接下来我应该做什么? $ brew search screen imgur-screenshot screen
我有一个在服务器端工作的 UDP 套接字应用程序。为了测试服务器端,我编写了一个简单的 python 客户端程序,它发送消息“hello world how are you”。服务器随后应接收消息,将
我有一个 shell 脚本,它运行一个 Python 程序来预处理一些数据,然后运行一个 R 程序来执行一些长时间运行的任务。我正在学习使用 Docker 并且我一直在运行 FROM r-base:l
在 Linux 中。我有一个 c 程序,它读取一个 2048 字节的文本文件作为输入。我想从 Python 脚本启动 c 程序。我希望 Python 脚本将文本字符串作为参数传递给 c 程序,而不是将
前言 最近开始整理笔记里的库存草稿,本文是 23 年 5 月创建的了(因为中途转移到 onedrive,可能还不止) 网页调起电脑程序是经常用到的场景,比如百度网盘下载,加入 QQ 群之类的 我
对于一个类,我被要求编写一个 VHDL 程序,该程序接受两个整数输入 A 和 B,并用 A+B 替换 A,用 A-B 替换 B。我编写了以下程序和测试平台。它完成了实现和行为语法检查,但它不会模拟。尽
module Algorithm where import System.Random import Data.Maybe import Data.List type Atom = String ty
我想找到两个以上数字的最小公倍数 求给定N个数的最小公倍数的C++程序 最佳答案 int lcm(int a, int b) { return (a/gcd(a,b))*b; } 对于gcd,请查看
这个程序有错误。谁能解决这个问题? Error is :TempRecord already defines a member called 'this' with the same paramete
当我运行下面的程序时,我在 str1 和 str2 中得到了垃圾值。所以 #include #include #include using namespace std; int main() {
这是我的作业: 一对刚出生的兔子(一公一母)被放在田里。兔子在一个月大时可以交配,因此在第二个月的月底,每对兔子都会生出两对新兔子,然后死去。 注:在第0个月,有0对兔子。第 1 个月,有 1 对兔子
我编写了一个程序,通过对字母使用 switch 命令将十进制字符串转换为十六进制,但是如果我使用 char,该程序无法正常工作!没有 switch 我无法处理 9 以上的数字。我希望你能理解我,因为我
我是 C++ 新手(虽然我有一些 C 语言经验)和 MySQL,我正在尝试制作一个从 MySQL 读取数据库的程序,我一直在关注这个 tutorial但当我尝试“构建”解决方案时出现错误。 (我正在使
仍然是一个初学者,只是尝试使用 swift 中的一些基本函数。 有人能告诉我这段代码有什么问题吗? import UIKit var guessInt: Int var randomNum = arc
我正在用 C++11 编写一个函数,它采用 constant1 + constant2 形式的表达式并将它们折叠起来。 constant1 和 constant2 存储在 std::string 中,
我用 C++ 编写了这段代码,使用运算符重载对 2 个矩阵进行加法和乘法运算。当我执行代码时,它会在第 57 行和第 59 行产生错误,非法结构操作(两行都出现相同的错误)。请解释我的错误。提前致谢:
我是 C++ 的初学者,我想编写一个简单的程序来交换字符串中的两个字符。 例如;我们输入这个字符串:“EXAMPLE”,我们给它交换这两个字符:“E”和“A”,输出应该类似于“AXEMPLA”。 我在
我需要以下代码的帮助: 声明 3 个 double 类型变量,每个代表三角形的三个边中的一个。 提示用户为第一面输入一个值,然后 将用户的输入设置为您创建的代表三角形第一条边的变量。 将最后 2 个步
我是一名优秀的程序员,十分优秀!