zoukankan      html  css  js  c++  java
  • python全栈开发day113-DBUtils(pymysql数据连接池)、Request管理上下文分析

    1.DBUtils(pymysql数据连接池)

    import pymysql
    from DBUtils.PooledDB import PooledDB
    
    POOL = PooledDB(
        creator=pymysql,  # 使用链接数据库的模块
        maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数
        mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
        maxcached=5,  # 链接池中最多闲置的链接,0和None不限制
        maxshared=3,
        # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
        blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
        maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制
        setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
        ping=0,
        # ping MySQL服务端,检查是否服务可用。
        # 如:0 = None = never,
        # 1 = default = whenever it is requested,
        # 2 = when a cursor is created,
        # 4 = when a query is executed,
        # 7 = always
        host='127.0.0.1',
        port=3306,
        user='root',
        password='wcy123',
        database='flask',
        charset='utf8'
    )
    sql = "select * from student"
    
    
    def get_conn():
        conn = POOL.connection()
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        return conn, cursor
    
    
    def reset_conn(conn, cursor):
        conn.close()
        cursor.close()
    
    
    def fetch_all(sql, *args):
        conn, cursor = get_conn()
        cursor.execute(sql, args)
        ret_ = cursor.fetchall()
        reset_conn(conn, cursor)
        return ret_
    
    
    def fetch_one(sql, *args):
        conn, cursor = get_conn()
        cursor.execute(sql, args)
        ret_ = cursor.fetchone()
        reset_conn(conn, cursor)
        return ret_
    
    
    ret1 = fetch_all(sql, )
    print(ret1)
    ret2 = fetch_one(sql, )
    print(ret2)
    sqlHelper

    2.request管理上下文分析
     

    1) 简单werkzeug服务启动:

      

    from werkzeug.serving import run_simple
    from werkzeug.wrappers import Request, Response
    
    
    @Request.application
    def app(request):
        print(request.method)
        return Response("200 ok")
    
    
    run_simple("127.0.0.1", 9527, application=app)
    werkzeug_demo

    2) from threading import local
      

    Python: threading.local是全局变量但是它的值却在当前调用它的线程当中
    
    在threading module中,有一个非常特别的类local。一旦在主线程实例化了一个local,它会一直活在主线程中,并且又主线程启动的子线程调用这个local实例时,它的值将会保存在相应的子线程的字典中。
    
    我们先看看测试代码:
    
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # Description: test the threading.local class
    # Create: 2008-6-4
    # Author: MK2[fengmk2@gmail.com]
    from threading import local, enumerate, Thread, currentThread
    
    local_data = local()
    local_data.name = 'local_data'
    
    class TestThread(Thread):
            def run(self):
                    print currentThread()
                    print local_data.__dict__
                    local_data.name = self.getName()
                    local_data.add_by_sub_thread = self.getName()
                    print local_data.__dict__
    
    if __name__ == '__main__':
            print currentThread()
            print local_data.__dict__
            
            t1 = TestThread()
            t1.start()
            t1.join()
            
            t2 = TestThread()
            t2.start()
            t2.join()
            
            print currentThread()
            print local_data.__dict__
    运行结果:
    <_MainThread(MainThread, started)>
    {'name': 'local_data'}
    <TestThread(Thread-1, started)>
    {}
    {'add_by_sub_thread': 'Thread-1', 'name': 'Thread-1'}
    <TestThread(Thread-2, started)>
    {}
    {'add_by_sub_thread': 'Thread-2', 'name': 'Thread-2'}
    <_MainThread(MainThread, started)>
    {'name': 'local_data'}
    
     
    
    主线程中的local_data并没有被改变,而子线程中的local_data各自都不相同。
    
    怎么这么神奇?local_data具有全局访问权,主线程,子线程都能访问它,但是它的值却是各当前线程有关,究竟什么奥秘在这里呢?
    
    查看了一下local的源代码,发现就神奇在_path()方法中:
    
    def _patch(self):
        key = object.__getattribute__(self, '_local__key')
        d = currentThread().__dict__.get(key)
        if d is None:
            d = {}
            currentThread().__dict__[key] = d
            object.__setattr__(self, '__dict__', d)
    
            # we have a new instance dict, so call out __init__ if we have
            # one
            cls = type(self)
            if cls.__init__ is not object.__init__:
                args, kw = object.__getattribute__(self, '_local__args')
                cls.__init__(self, *args, **kw)
        else:
            object.__setattr__(self, '__dict__', d)
     
    每次调用local实例的属性前,local都会调用这个方法,找到它保存值的地方.
    
    d = currentThread().__dict__.get(key)  就是这个地方,确定了local_data值的保存位置。所以子线程访问local_data时,并不是获取主线程的local_data的值,在子线程第一次访问它是,它是一个空白的字典对象,所以local_data.__dict__为 {},就像我们的输出结果一样。
    
    如果想在当前线程保存一个全局值,并且各自线程互不干扰,使用local类吧。
    Python: threading.local是全局变量但是它的值却在当前调用它的线程当中

    3) 

    4) 什么时候执行的app.__call__函数,怎么把WSGIRequestHandler初始化传进入的从socket接收的内容request传给app处理函数的?

    1.什么时候执行的app.__call__函数
        run_simple(host, port, self, **options)中
        通过inner()函数:
             srv = make_server(hostname, port, application, threaded,
                              processes, request_handler,
                              passthrough_errors, ssl_context,
                              fd=fd)
            # srv为BaseWSGIServer实例:
                BaseWSGIServer(host, port, app, request_handler,
                                  passthrough_errors, ssl_context, fd=fd)
                request_handler 处理函数为WSGIRequestHandler
                WSGIRequestHandler处理函数通过:
                    1、BaseWSGIServer的__init__,
                        2、HTTPServer.__init__(self, get_sockaddr(host, int(port),
                                                   self.address_family), handler)
                            3、TCPServer的__init__,
                                4、传给BaseServer的self.RequestHandlerClass = RequestHandlerClass
             srv.serve_forever() 
                继承关系:BaseWSGIServer-》HTTPServer-》TCPServer-》BaseServer
                    :
                        def serve_forever(self, poll_interval=0.5):
                            self._handle_request_noblock()
    
                             def _handle_request_noblock(self):
                                self.process_request(request, client_address)
                                    def process_request(self, request, client_address):
                                        self.finish_request(request, client_address)
                                            def finish_request(self, request, client_address):
                                            self.RequestHandlerClass(request, client_address, self) 
                                            # 处理函数实例化,就是WSGIRequestHandler实例化
                                                初始化会执行self.handle()方法:
                                                WSGIRequestHandler-》BaseHTTPRequestHandler-》StreamRequestHandler-》BaseRequestHandler:    
                                                    def __init__(self, request, client_address, server):
                                                                        self.request = request
                                                                        self.client_address = client_address
                                                                        self.server = server
                                                                        self.setup()
                                                                        try:
                                                                            self.handle()
                                                                        finally:
                                                                            self.finish()
                                                                            
                                                    WSGIRequestHandler:def handle(self):
                                                            rv = BaseHTTPRequestHandler.handle(self)
                                                                    def handle(self):
                                                                        self.handle_one_request()
    
                                                    def handle_one_request(self):
                                                            return self.run_wsgi()
                                                    execute(self.server.app)
                                                    def execute(app):
                                                        application_iter = app(environ, start_response)
                                                        
                                                        
    2. 怎么把WSGIRequestHandler初始化传进入的从socket接收的内容request传给app处理函数的?
        
        WSGIRequestHandler的祖辈类StreamRequestHandler,
        在setup函数中将request处理后传给self.rfile
                def setup(self):
                    self.connection = self.request
                    if self.timeout is not None:
                        self.connection.settimeout(self.timeout)
                    if self.disable_nagle_algorithm:
                        self.connection.setsockopt(socket.IPPROTO_TCP,
                                                   socket.TCP_NODELAY, True)
                    self.rfile = self.connection.makefile('rb', self.rbufsize)
                    if self.wbufsize == 0:
                        self.wfile = _SocketWriter(self.connection)
                    else:
                        self.wfile = self.connection.makefile('wb', self.wbufsize)
                        
            在WSGIRequestHandler中将self.rfile传给environ:
                environ = {
                    'wsgi.version':         (1, 0),
                    'wsgi.url_scheme':      url_scheme,
                    'wsgi.input':           self.rfile,
                    'wsgi.errors':          sys.stderr,
                    'wsgi.multithread':     self.server.multithread,
                    'wsgi.multiprocess':    self.server.multiprocess,
                    'wsgi.run_once':        False,
                    'werkzeug.server.shutdown': shutdown_server,
                    'SERVER_SOFTWARE':      self.server_version,
                    'REQUEST_METHOD':       self.command,
                    'SCRIPT_NAME':          '',
                    'PATH_INFO':            wsgi_encoding_dance(path_info),
                    'QUERY_STRING':         wsgi_encoding_dance(request_url.query),
                    'REMOTE_ADDR':          self.address_string(),
                    'REMOTE_PORT':          self.port_integer(),
                    'SERVER_NAME':          self.server.server_address[0],
                    'SERVER_PORT':          str(self.server.server_address[1]),
                    'SERVER_PROTOCOL':      self.request_version
                }
            通过application_iter = app(environ, start_response)传给app,在通过app传给request实例化:
                request = app.request_class(environ)
    什么时候执行的app.__call__函数

    5)简要流程:

    问题一:flask和django的区别:
      对于django来说,内部组件特别多,自身功能强大,有点大而全,而flask,内置组件很少,但是它的第三方组件很多,扩展性强,有点短小精悍,而它们之间也有相似之处,
      因为它们两个框架都没有写sockte,都是基于wsgi协议做的,在此之外,flask框架中的上下文管理较为耀眼。
    
      
      相同点:它们两个框架都没有写sockte,都是基于wsgi协议做的
      请求相关数据传递的方式不同:django:通过传递request参数取值
                    flask:见问题二
               组件不同:django组件多
                    flask组件少,第三方组件丰富
    
    问题1.1: flask上下文管理:
      简单来说,falsk上下文管理可以分为三个阶段:
            1、请求进来时,将请求相关的数据放入上下问管理中
            2、在视图函数中,要去上下文管理中取值
            3、请求响应,要将上下文管理中的数据清除
      
      详细点来说:
            1、请求刚进来,将request,session封装在RequestContext类中,app,g封装在AppContext类中,并通过LocalStack将requestcontext和appcontext放入Local类中
            2、视图函数中,通过localproxy--->偏函数--->localstack--->local取值
            3、请求相应时,先执行save.session()再各自执行pop(),将local中的数据清除
    简要流程
  • 相关阅读:
    pandas Dataframe filter
    process xlsx with pandas
    data manipulate in excel with easyExcel class
    modify registry in user environment
    add number line in vim
    java import webservice
    ctypes MessageBoxA
    music 163 lyrics
    【python实例】自动贩卖机
    【python基础】sys模块(库)方法汇总
  • 原文地址:https://www.cnblogs.com/wuchenggong/p/9780265.html
Copyright © 2011-2022 走看看