调用tornado.options.parse_command_line时,将自动设置logging的级别

通过源码可以发现,tornado中也是大量使用了python中的logging模块来处理日志操作。

但tornado在处理日志的时候,特别是tornado.options.parse_command_line()时将根日志的级别设置为info,这点需要特别注意!

如果在tornado.options.parse_command_line()之前程序对logging的日志级别进行了设置,则很有可能会被tornado进行改写,这点需要特别注意。 通过下面的代码可以很容易就能看出tornado对跟logger的级别进行了调整:

import os
import ssl
import logging
from tornado.httpserver import HTTPServer
from tornado.web import Application, RequestHandler
from tornado.ioloop import IOLoop
import tornado.options
from tornado.options import define, options
 
 
LOG = logging.getLogger(__name__)
 
define("port", default=8000, help="run on the given port", type=int)
class TestHandler(RequestHandler):
    def get(self):
        self.write("Hello, World!\n")
 
application = Application([
    (r"/", TestHandler),],
    debug = True)
 
if __name__ == "__main__":
    print "main 1 getEffectiveLevel = ", LOG.getEffectiveLevel()
    print "tornado default log level = "tornado.options.options.logging
    tornado.options.options.logging = "debug"
    tornado.options.parse_command_line()
 
    print "main getEffectiveLevel = ", LOG.getEffectiveLevel()
    # server = HTTPServer(application,ssl_options={
    #        "certfile": os.path.join(os.path.abspath("."), "cert.pem"),
    #        "keyfile": os.path.join(os.path.abspath("."), "privatekey.pem"),
    #    })
    server = HTTPServer(applicatio)
    server.listen(options.port)
    IOLoop.instance().start()

 

 对根logger的日志级别进行更改主要是tornado的tornado.options所为,源码如下:

def parse_command_line(self, args=None):
        if args is None:
            args = sys.argv
        remaining = []
        for i in xrange(1, len(args)):
            # All things after the last option are command line arguments
            if not args[i].startswith("-"):
                remaining = args[i:]
                break
            if args[i] == "--":
                remaining = args[i + 1:]
                break
            arg = args[i].lstrip("-")
            name, equals, value = arg.partition("=")
            name = name.replace('-', '_')
            if not name in self:
                print_help()
                raise Error('Unrecognized command line option: %r' % name)
            option = self[name]
            if not equals:
                if option.type == bool:
                    value = "true"
                else:
                    raise Error('Option %r requires a value' % name)
            option.parse(value)
        if self.help:
            print_help()
            sys.exit(0)
 
        # Set up log level and pretty console logging by default
        if self.logging != 'none':
            logging.getLogger().setLevel(getattr(logging, self.logging.upper()))
            enable_pretty_logging()
 
        return remaining

 

# Default options
define("help", type=bool, help="show this help information")
define("logging", default="info",
       help=("Set the Python log level. If 'none', tornado won't touch the "
             "logging configuration."),
       metavar="debug|info|warning|error|none")

可以看到,tornado.options在parse_command_line的时候,会判断self.logging 是否为none,非none时执行logging.getLogger().setLevel(getattr(logging, self.logging.upper())),也就是对根logger的level进行设置。

在tornado.options被import的时候定义了一个logging,parse_command_line的时候将logging的根级别设置为info。

总之,在tornado应用中,应该特别注意logging级别设置同tornado.options.parse_command_line的先后顺序。

 

 

1. tornado logging使用的python内置的logging模块
2. 在tornado/options.py 中定义了对logging配置项的一些定义(如果需要添加启动参数,需要在对应的代码中导入options模块),以下是一些在options.py中定义的Option
-help
-logging = info|warning|error|none
-log_to_stderr = True|False
-log_file_prefix = your path
-log_file_max_size = int
-log_file_num_backups = int
3. 我们可以通过添加一启动项-log_file_prefix=your complete log path,将整个webapp相关的日志文件写入到指定文件中(同时需要添加如下代码):
from tornado.options import define, options
tornado.options.parse_command_line()
4. 然后通过类似启动命令:python helloworld.py -log_file_prefix=your ** path
由于tornado优良的可扩展性,我们可以同时启动多个tornado server进程,这里我们提出这种需求场景,如何记录各个端口的server日志?
相关代码:
import logging
import tornado.httpserver
import tornado.ioloop
import tornado.web
from tornado.options import define, options
define("port", default=8083, help="Run server on a specific port", type=int)
class MainHandler(tornado.web.RequestHandler):
def get(self):
logging.info("**Request to MainHandler!")
self.write("Hello to the Tornado world!")
settings = {
"debug": True,
}
application = tornado.web.Application([
(r"/", MainHandler),
], **settings)
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
'''
Get the option(s) from the startup command line if ever.
In this tutorial, we define own "port" option to change the
port via the command line, and then we can run multiple tornado
processes at different ports.
'''
tornado.options.parse_command_line()
# This line should be after the parse_command_line()
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
1. 这里我们自定义一个可根据启动参数来修改的监听端口。
2. 通过-log_file_prefix选项,我们可以将输出日志文件与端口号绑定,用于区分,相关的启动命令类似:
python helloworld.py -port=8091 -log_file_prefix=your complete path/test_log@8091.log
python helloworld.py -port=8092 -log_file_prefix=your complete path/test_log@8092.log
通过以上方式,我们就可以记录多个端口的相关日志

tornado.options.parse_command_line()

 

 这一句是解析命令行参数,函数定义在tornado/options.py里。注意,在options.py里有两个parse_command_line()的定义。一个是OptionParser类的成员函数:

class OptionParser(object):
def parse_command_line(args=None, final=True):

 

另一个是普通的函数,不过它的实现是直接调用OptionParser的实现。

def parse_command_line(args=None, final=True):
    return options.parse_command_line(args, final=final) 

 

 

 

 

直接看OptionParser中的实现。简短的注释,parse_command_line()默认是解析sys.argv中的参数。我们在运行helloworld.py时,后面跟的参数在这里处理。命令行参数的解析过程很简单,没有什么需要特别关注。再者,我们现在没有使用任何命令行参数,所以先略过。

posted on 2017-08-19 13:45  myworldworld  阅读(1306)  评论(0)    收藏  举报

导航