如何覆盖BaseHTTPRequestHandler log_message()方法,将日志记录到文件而不是控制台(sys.stderr)?

9

我正在使用BaseHTTPServer.HTTPServer创建一个WebService。

我想将以下内容记录到文件中而不是控制台。但是我还没有找到一种方法来实现。

10.23.23.19 - - [29/Nov/2013 08:39:06] "GET / HTTP/1.1" 200 -
10.23.23.19 - - [29/Nov/2013 08:39:06] "POST / HTTP/1.1" 200 -
10.24.20.14 - - [29/Nov/2013 08:39:27] "POST / HTTP/1.1" 200 -
10.24.20.14 - - [29/Nov/2013 08:39:31] "POST / HTTP/1.1" 200 -

我的代码长这样:

from BaseHTTPServer import HTTPServer
from pysimplesoap.server import SoapDispatcher, SOAPHandler
.
# The rest of the code
.
.
httpd = HTTPServer(("", 8059),SOAPHandler)
    httpd.dispatcher = dispatcher
    httpd.serve_forever()

我正在使用Python 2.6


我一直在网上寻找解决方案,但我发现的都是如何“关闭”控制台日志记录而不是如何将其重定向到文件。我找到的最好和最简单的解决方案是:from BaseHTTPServer import BaseHTTPRequestHandler class QuietBaseHTTPRequestHandler(BaseHTTPRequestHandler): def send_response(self, code, message=None): pass - Phil
一个比较老的问题,但是仍然比那篇已经回答了如何静默/安静HTTPServer和BasicHTTPRequestHandler的stderr输出的帖子新3年。=) - Mike 'Pomax' Kamermans
4个回答

9
如果您阅读BaseHTTPRequestHandler的文档或源代码,您会发现所有日志记录都通过BaseHTTPRequestHandler.log_message()进行,该文档字符串明确指定:
记录任意消息。 这是由所有其他日志记录函数使用的。 如果您有特定的日志记录要求,请覆盖它。
因此,解决方案显然是保留.send_response()(显然您希望发送响应),并将.log_message()替换为调用适当的记录器(参见http://docs.python.org/2/library/logging.html),这是在Python中处理日志记录的清洁和灵活方式,或者如果您只想要快速的黑客写入文件系统文件。

请注意,通常情况下您不希望覆盖主 log_message 函数,而只是覆盖 log_request 处理程序,因为您通常不关心持续的成功请求流,但您确实关心错误。 - Mike 'Pomax' Kamermans

6

我找到了一个解决方案。

我在pysimplesoap/server.py文件中创建了一个带有FileHandler的记录器。 我在必要的导入之后立即创建了该记录器。

httpdkenlogger = logging.getLogger('httpd-ken')
#setup file handler
fh = logging.FileHandler('/opt/python/dev/interim/httpd-kenserver.3.log')
fh.setLevel(logging.INFO)
frmt = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(frmt)
# Add this handler to the logger
httpdkenlogger.addHandler(fh)

接下来,在SOAPHandler类的定义中,我决定按照以下方式覆盖log_message函数:

class SOAPHandler(BaseHTTPRequestHandler):
    def log_message(self, format, *args):
        httpdkenlogger.info("%s - - [%s] %s\n" % (self.address_string(),self.log_date_time_string(),format%args))

1

我成功地通过以下方式在控制台上抑制了 BaseHTTPRequestHandler 的信息:

class https_server(BaseHTTPRequestHandler):
    def log_request(self, code): 
        pass
    ...

源代码


0
在手册中指出:
BaseHTTPRequestHandler has the following instance variables:

log_message(format, ...)

这个函数的参数没有列出来,但可以通过试错来确定:

class MyClass(BaseHTTPRequestHandler):

    def fn( self, *args ):
        print( args )

    def do_POST(self):
        self.log_message = self.fn

有四个参数需要显示(第一个是格式,然后是请求信息、状态码和另一个字段)。

因此,可以使用类似以下的内容:

    def myLog( self, fmt, request, code, other ):
        syslog( LOG_INFO, '%s %s' % ( code, request) )

    def do_POST(self):
        self.log_message = self.myLog

可以将日志记录到自己的端点。

我唯一看到的缺点是需要在每个处理程序实例上替换log_message


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