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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM