• tornado 的 define 和options方法解读


    一、源码解读

    tornado是facebook开源的非阻塞web容器,类似java的netty,tornado.options是负责解析tornado容器的全局参数的,同时也能够解析命令行传递的参数和从配置文件中解析参数。使用步骤如下:

    1.  源码中的示例代码,定义全局变量:

    from tornado.options import define, options
    define("mysql_host", default="127.0.0.1:3306", help="Main user DB")
    define("memcache_hosts", default="127.0.0.1:11011", multiple=True,
           help="Main user memcache servers")
    def connect():
        db = database.Connection(options.mysql_host)
        ...
    
     

    2.  在模块的main函数中解析命令行参数或者配置文件

    Your ``main()`` method can parse the command line or parse a config file with
    either::
        tornado.options.parse_command_line()
        # or
        tornado.options.parse_config_file("/etc/server.conf")

    命令行参数格式:--myoption=myvalue

    配置文件可以是python文件,参数格式为:

    myoption = "myvalue"
    myotheroption = "myothervalue"

    3.  Tornado.options默认是定义为单例模式的,通过tornado.options.options对象来维护全局参数,如果在线程中需要维护自己的变量,也可以使用tornado.options. OptionParser对象来维护参数。tornado.options.options就是通过实例OptionParser的对象来实现的,而且把define、parse_command_line、parse_config_file放到tornado.options 包中,可以直接使用,与调用tornado.options.options的方法是一致的。代码如下:

    options = OptionParser()
    """Global options object.
    All defined options are available as attributes on this object.
    """
    def define(name, default=None, type=None, help=None, metavar=None,
               multiple=False, group=None, callback=None):
        """Defines an option in the global namespace.
        See `OptionParser.define`.
        """
        return options.define(name, default=default, type=type, help=help,
                              metavar=metavar, multiple=multiple, group=group,
                              callback=callback)
    def parse_command_line(args=None, final=True):
        """Parses global options from the command line.
        See `OptionParser.parse_command_line`.
        """
        return options.parse_command_line(args, final=final)
    def parse_config_file(path, final=True):
        """Parses global options from a config file.
        See `OptionParser.parse_config_file`.
        """
        return options.parse_config_file(path, final=final)

    二、应用

        # 在tornado.options.options配置变量名
        from tornado.options import define, options
        define('debug', default=True, help='enable debug mode')
        define('project_path', default=sys.path[0], help='deploy_path')
        define('port', default=8888, help='run on this port', type=int)
        # 从命令行中解析参数信息, 如 python web.py --port=9002, 这里的port解析
        tornado.options.parse_command_line()

    使用参数

    使用options获取刚设置的参数
    
        from tornado.options import options
        ....
        application.listen(options.port)
        .....
        settings = {
            'debug': options.debug,
            }

    完整代码

        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
        # vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8:
        __author__ = 'okker.ma@gmail.com'
        
        import tornado.ioloop
        import tornado.web
        
        import os
        from tornado.options import options, define
        
        #在options中设置几个变量
        define('debug', default=True, help='enable debug mode')
        define('port', default=9002, help='run on this port', type=int)
        
        # 解析命令行, 有了这行,还可以看到日志...
        tornado.options.parse_command_line()
        
        class MainHandler(tornado.web.RequestHandler):
        
            def get(self):
                self.write("hello,a world")
        
        settings = {
                    'debug': options.debug,
                    'gzip': True,
                    'autoescape': None,
                    'xsrf_cookies': False,
                    'cookie_secret': 'xxxxxxx'
                }
        
        application = tornado.web.Application([
            (r'/', MainHandler)
        ], **settings)
        
        if __name__ == '__main__':
            application.listen(options.port)
            tornado.ioloop.IOLoop.instance().start()

    运行:

        python web.py --port=9002 --debug=True

     示例二

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    
    import tornado.httpserver
    import tornado.ioloop
    import tornado.web
    from tornado.options import define, options
    from test import aa
    
    define('config', default=None, help='tornado settings file', type=str)
    
    options.parse_command_line()
    if options.config:
        # print(options.settings)
        aa()
    else:
        raise Exception("You must add a xxx.py at settings/ folder, then run: 'python app.py --settings=user'")
    
    
    class IndexHandler(tornado.web.RequestHandler):
        def get(self):
            greeting = self.get_argument('greeting', 'Hello')
            self.write(greeting + ', friendly user!')
    
    
    if __name__ == "__main__":
        app = tornado.web.Application(
            handlers=[(r"/", IndexHandler)]
        )
        http_server = tornado.httpserver.HTTPServer(app)
        http_server.listen(8000)
        tornado.ioloop.IOLoop.current().start()
    main.py
    from tornado.options import options
    import importlib
    
    
    # db_config = importlib.import_module('settings.%s.db_config'%options.settings)
    #
    # options.config = {
    #     'MONGO': db_config.MONGO,
    #     'SETTINGS': {},
    # }
    
    def aa():
        data = dict(options.items())
        print("asdfasdf", data["config"])
    other.py

     注意 tornado如果启动多进程, option方法是不可实现的, 报错

    tornado.options.Error: Option 'lalala' already defined in app.py

    没找到解决办法

    本文参考链接:(其实这篇是抄的, 哈哈哈)

      1. https://blog.csdn.net/wgw335363240/article/details/50755782

      2. https://my.oschina.net/jiemachina/blog/204875

    三、多进程解决办法 ---》哈哈哈,找到解决办法啦~

    怎么解决呢?,单利模式嘛,哈哈哈

    一定要把options的东西放启动脚本的最上面, 要不下面调用的时候报错

    问题出在哪呢?

    多进程是启动多个,当已经define定义key的时候, OK, 可是同时启动多个啊, memory中已经有定义好的define的你定义的key了呀

    判断一下嘛, 就好啦

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from tornado.options import define, options
    
    try:
        if options.lalala:
            pass
    except:
        define('conf', default='zk_css.cnf', help='tornado settings file', type=str)
    
    import tornado
    import tornado.ioloop
    import tornado.web
    import os, sys
    from tornado.httpserver import HTTPServer
    from tornado.options import define, options
    from controllers.home_handlers import My404, write_error
    from common.util.include_url_model import url_wrapper, include
    from common.base import Config
    
    ServerPort = Config().get_content("server")
    define("port", default=ServerPort["serverport"], type=int)
    
    options.parse_command_line()
    
    _ROOT_PATH = os.path.dirname(__file__)
    ROOT_JOIN = lambda sub_dir: os.path.join(_ROOT_PATH, sub_dir)
    
    router = url_wrapper([
        (r'', include('urls')),
    ])
    
    settings = dict(
        template_path=ROOT_JOIN('views'),
        static_path=ROOT_JOIN('static'),
        # cookie_secret=Env.COOKIE_SEC,
        default_handler_class=None,
        debug=False
    )
    
    tornado.web.RequestHandler.write_error = write_error
    application = tornado.web.Application(router, **settings)
    
    if __name__ == "__main__":
        server = HTTPServer(application, max_buffer_size=504857600)
        server.bind(options.port, address="0.0.0.0")
        server.start(10)  # Forks multiple sub-process
        tornado.ioloop.IOLoop.current().start()
    app.py
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import configparser
    import os, json, base64
    from decimal import Decimal
    import datetime, time
    import pymongo
    # import MySQLdb
    import pymysql
    from common.log.loger import Logger
    import datetime, time, uuid, re
    import hashlib
    from common.error import *
    from other_url import BaseConf
    from tornado.options import define, options
    
    def my_options(arg):
        return dict(options.items())[arg]
    
    
    class Config(object):
        """
        # Config().get_content("user_information")
        """
    
        def __init__(self):
    
            # file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "conf", BaseConf.BaseCnf)
            file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "conf", my_options("conf"))
            self.cf = configparser.ConfigParser()
            self.cf.read(file_path)
    
        def get_sections(self):
            return self.cf.sections()
    
        def get_options(self, section):
            return self.cf.options(section)
    
        def get_content(self, section):
            result = {}
            for option in self.get_options(section):
                value = self.cf.get(section, option)
                result[option] = int(value) if value.isdigit() else value
            return result
    Base.py

    分割线

    ==========================================

    屁, 他娘的,根本没解决,大爷的, 问题出在哪儿了,百度FORK() 函数,跟他有关

    解决办法

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from tornado.options import define, options
    
    if "conf" in dict(options.items()):
        pass
    else:
        define("conf", default='zk_css.cnf', help='tornado settings file', type=str)
    
    import tornado.web
    import os
    from tornado.httpserver import HTTPServer
    from tornado.options import define, options
    from controllers.home_handlers import My404, write_error
    from common.util.include_url_model import url_wrapper, include
    from common.base import Config
    
    ServerPort = Config().get_content("server")
    define("port", default=ServerPort["serverport"], type=int)
    
    options.parse_command_line()
    
    _ROOT_PATH = os.path.dirname(__file__)
    ROOT_JOIN = lambda sub_dir: os.path.join(_ROOT_PATH, sub_dir)
    
    router = url_wrapper([
        (r'', include('urls')),
    ])
    
    settings = dict(
        template_path=ROOT_JOIN('views'),
        static_path=ROOT_JOIN('static'),
        # cookie_secret=Env.COOKIE_SEC,
        default_handler_class=None,
        debug=False
    )
    
    tornado.web.RequestHandler.write_error = write_error
    application = tornado.web.Application(router, **settings)
    
    if __name__ == "__main__":
    
        from tornado.netutil import bind_sockets
        from tornado.process import fork_processes
        from tornado.ioloop import IOLoop
    
        sockets = bind_sockets(port=options.port, address="0.0.0.0")
        fork_processes(10)
        server = HTTPServer(application, max_buffer_size=504857600)
        server.add_sockets(sockets)
        IOLoop.current().start()

    分割线

    ===========================================

    草,又特么不行了,为什么呢? 因为出现了两种不同结果, 麻痹的, 没找到解决办法

    root@corleone:/opt/code/my_code/zk_css# python3 app.py --port=8010 --conf=zk_css_2.cnf
    base:  zk_css.cnf
    base:  zk_css.cnf
    base:  zk_css.cnf   ----》 看这儿
    base:  zk_css.cnf
    base:  zk_css_2.cnf  --》  看这儿
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    /usr/local/lib/python3.5/dist-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
      from pandas.core import datetools
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    base:  zk_css_2.cnf
    zk_css_2.cnf
    8010
    [I 180906 16:56:49 process:133] Starting 10 processes
  • 相关阅读:
    二分图匹配详解
    树状数组略解
    质数算法略解
    主席树详解
    线段树略解
    【题解】Luogu P2073 送花
    【题解】Luogu P1533 可怜的狗狗
    分块入门
    【题解】Luogu CF86D Powerful array
    【题解】Luogu UVA12345 Dynamic len(set(a[L:R]))
  • 原文地址:https://www.cnblogs.com/renfanzi/p/9585167.html
Copyright © 2020-2023  润新知