Search code examples
pythonpython-3.xterminalstderrweb.py

How to suppress web.py output?


I am trying to suppress the web.py output from the console. I do not wish to suppress all output to stderr or redirect the output, but merely stop it from printing statements such as the following to the console.

127.0.0.1:57691 - - [06/Mar/2018 22:25:43] "HTTP/1.1 GET /api/getDimensionColumnConstraints" - 200 OK

I have tried adding the web.config.debug = False statement as the first line in my main() function and it still prints this for every API call.


Solution

  • The built-in server for web.py sends the HTTP info and other errors to stderr by default. I'm with you -- I want the errors, but don't want all the HTTP statements.

    So, here's what you can do.

    1. Create a custom Logger

    2. Intercept calls within the logger, tossing out log records matching the pattern.

    Not so hard, you'll create a basic wsgi application middleware to intercept:

    import logging
    class Log:
        def __init__(self, xapp, logname="wsgi"):
            class O:
                def __init__(self, xapp, logname="wsgi"):
                    self.logger = logging.getLogger(logname)
                def write(self, s):
                    if s[-1] == '\n':
                        s = s[:-1]
                    if s == "":
                        return
                    if self.ignore(s):
                        return
                    self.logger.debug(s)
            self.app = xapp
            self.f = O(logname)
        def __call__(self, environ, start_response):
            environ['wsgi.errors'] = self.f
            return self.app(environ, start_response)
    

    Add that middleware into your __main__ initialization of the application. You probably have something like:

    if __name__ == '__main__':
        app = web.application(urls, globals())
        app.run()
    

    Change the run() to add the middleware:

        app.run(Log)
    

    Now the second part. See the self.ignore(s) within O.write() above? Use that to decide to process or ignore the logging statement, for example I do:

    def ignore(self, s):
        if not all([web.config.get('debug_http', False),
                   any(['"HTTP/1.1 GET ' in s,
                        '"HTTP/1.1 POST ' in s])]):
            return True
        return False
    

    Which basically says if the string to print contains 'HTTP...' ignore it. I've added the check to a global flag 'debug_http', which allows me to set that (somewhere, anywhere, anyhow) to enable / disable this item.