Python 烧瓶-当使用logging.handlers.HTTPHandler发布错误时,您可以重定向或刷新这些错误吗?
我有一个在整个系统中使用的记录器,它使用HTTP处理程序报告错误,然后flask捕获它们,我希望能够刷新它们,以便用户能够看到错误 我特意不使用flasks normal logger,因为它需要扩展到整个系统,以便正确记录错误 然而,尽管flask似乎可以捕获错误并从logs视图中打印出来,但它无法将错误闪存给用户或重定向到显示错误的页面 以下是我的处理程序/记录器设置的相关部分:Python 烧瓶-当使用logging.handlers.HTTPHandler发布错误时,您可以重定向或刷新这些错误吗?,python,flask,Python,Flask,我有一个在整个系统中使用的记录器,它使用HTTP处理程序报告错误,然后flask捕获它们,我希望能够刷新它们,以便用户能够看到错误 我特意不使用flasks normal logger,因为它需要扩展到整个系统,以便正确记录错误 然而,尽管flask似乎可以捕获错误并从logs视图中打印出来,但它无法将错误闪存给用户或重定向到显示错误的页面 以下是我的处理程序/记录器设置的相关部分: 'error_handler': { 'class': 'logging.handlers.HTTPHa
'error_handler': {
'class': 'logging.handlers.HTTPHandler',
'formatter': 'debug_formatter',
'level': 'WARNING',
'filters': ['Web_filter'],
'host': 'localhost:5000',
'url' : '/logs',
'method' : 'POST',
},
下面是捕获这些错误的视图:
@app.route('/logs' , methods = ["GET","POST"])
def logs():
message = str(request.form['message'])
print("message: " + message) #this works
flash(message) #this doesn't
return render_template('500_unhandled.html', title='ERROR', e = message) #neither does this
更新:我实际上切换了创建记录器的方法,因此它稍微简单一些,但仍然不起作用:
http_handler = HTTPHandler('localhost:5000','/logs',method='POST',)
http_handler.addFilter(WebFilter())
new_logger.addHandler(http_handler)
更新2:我尝试了只返回消息的建议,但这让我怀疑我在哪里可以访问此返回值,因此,如果您能提供更多帮助,我们将不胜感激。以下是该版本:
@app.route('/logs' , methods = ["GET","POST"])
def logs():
message = str(request.form['message'])
print("message: " + message) #this works
return message #this doesn't really do anything
我还尝试使用中止方法:
@app.route('/logs' , methods = ["GET","POST"])
def logs():
message = str(request.form['message'])
print("message: " + message) #this works
abort(500, message) #this doesn't work either
更新3:
我在view函数中添加了一条日志消息,只是想看看是否出于某种原因从阻止通信的其他位置或线程调用它。以下是两条不同的日志消息以及生成它们的代码:
@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
logger.error('test error')
Prints:
routes:Thread-1:test error
@app.route('/logs' , methods = ["GET","POST"])
def logs():
message = str(request.form['message'])
logger.info("where am i?")
print("message: " + message) #this works
abort(500, message)
Prints:
routes:Thread-2:where am i?
message: test error
它们在不同线程中的事实是有问题的还是正常的
更新4:我刚才注意到的另一件奇怪的事情是,我无法从logs视图访问会话变量。这让我觉得,出于某种原因,日志与应用程序的其他部分是分开的
更新5:为了重申我在评论中提到的一些非常奇怪的事情,abort语句可以工作并重定向到我的错误处理程序,但是错误页面“500.html”在重定向到主页之前只在屏幕上闪烁。以下是我的错误处理程序的代码:
@app.errorhandler(500)
def handle_500(e):
original = getattr(e, "original_exception", None)
if original is None:
# direct 500 error, such as abort(500)
print(e)
return render_template("500.html",e = e), 500
# wrapped unhandled error
return render_template("500_unhandled.html", e=original), 500
当您调用
logger.info()
时,它会向服务器发送带有消息的POST
请求,并查看函数logs()
处理此请求。它获取消息,打印它,闪烁它,并将页面返回到记录器请求。这样,消息就被打印出来了
当您在浏览器中访问此页面时,浏览器会向服务器发送无消息的GET
请求,再次查看函数logs()
处理此请求。它试图获取消息,但请求中没有消息。所以它既不会被打印也不会被闪现
要显示消息,您需要将它们存储在某个位置。当您收到
POST
请求时,将消息添加到数据库/数组/文件/etc。当您收到get
请求时检索消息并刷新它们,等等。请参阅下面的编辑以获得更好的答案
我不确定我是否清楚地理解了这个问题,但我会试一试
你的问题听起来像是HTML问题。闪烁要求您在返回的HTML模板中添加闪烁设置:您必须在返回的HTML中指定它必须显示您的闪烁消息:
HTML示例:
<h1>My HTML title</h1>
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
{% endwith %}
此模板(在本例中,包含_flash.html
)必须包含在项目目录中的/templates文件夹中才能正确访问,并且必须包含类似于上一个html代码的内容
最后,确保在函数中添加单独的部分来处理POST请求,而不仅仅是常规查看页面:
@app.route('/logs' , methods = ["GET","POST"])
def logs():
if request.method == "POST":
message = str(request.form['message'])
flash(message)
# goes back to same page so user can view messages
return redirect(url_for('logs'))
else:
# perhaps flashes messages and has form to POST messages
return render_template('contains_flash.html')
请记住,对于上述所有代码,用户必须到达您的url/logs
才能访问您的日志(闪现消息)
最后,解释建议的返回语句:iereturnmessage
。如果使用返回消息
,则当用户转到“url/log”时,它将显示与该消息等价的HTML。因此,它将返回您的消息,但没有任何HTML格式
编辑:考虑更多问题的答案
由于flash()。因此,闪烁显然不起作用。打印是有效的,因为您不会在web浏览器中(在不同的会话中)访问消息,而只是将消息打印到您可以看到它的终端上
相反,使用数据库存储记录的消息,然后将其显示给用户。一个相当容易设置的数据库是,您可以使用它
import sqlite3
# ... previous code
conn = sqlite3.connect('db.sqlite') # your db name
conn.row_factory = lambda cursor, row: row[0] # does not return tuple
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS errors
(message TEXT NOT NULL)''') # create table
conn.commit() # saves database operations
@app.route('/logs' , methods = ["GET","POST"])
def logs():
if request.method == "POST":
message = str(request.form['message'])
c.execute('INSERT INTO errors (message) VALUES (?)', (message,))
conn.commit()
# if not a POST, request must be from user:
errors = c.execute('SELECT message FROM errors').fetchall() # get all messages: this can be changed
return render_template('messages.html', errors=errors)
messages.html显示错误:
<h1>Errors below</h1>
{% for error in errors %}
<p>{{ error }}</p>
{% endfor %}
下面的错误
{错误%中的错误为%0}
{{error}}
{%endfor%}
现在,以上内容应该是存储记录错误的简单方法。根据需要向表中添加更多字段。这是因为HTTPHandler类是如何工作的。
它将向/log
端点发出错误消息。日志端点将呈现的html和消息返回给记录器。但是记录者不能用它做任何事情。它不会将值返回到用户的浏览器。所以什么也没有出现
该类的相关行。它甚至提到它对结果无能为力。
h.getresponse()#对结果无能为力
您是否尝试过对flash(message)
进行评论并仅使用返回消息
?我尝试过,由于您的建议,请查看我的更新以了解更多详细信息。您是否使用了此功能?是的,我正在使用@fcsrCool回复感谢您的回复,然而,我认为这是不正确的。首先,当处理POST
请求时,它不会闪烁或重定向,它只会打印这是我的帖子的关键。其次,我从未尝试通过浏览器访问日志视图,它只是用来处理传入的请求,而不是一个页面本身。为了证明这一点,我从中完全删除了GET
方法,其功能是相同的。你怎么知道POST
请求是透明的
<h1>Errors below</h1>
{% for error in errors %}
<p>{{ error }}</p>
{% endfor %}