python之路_flask架構_flask架構基礎(2)

來源:互聯網
上載者:User

標籤:ati   ica   自己的   建立資料庫   thread   .config   多少   必須   不同   

一、設定檔

  和django不同的是,django會為我們提供配置好的setting檔案,我們需要的配置都可以自動添加在setting檔案中即可,但是flask不是這樣,它是通過在內部為我們提供多種設定檔的介面,我們按照介面配置相關配置。簡單介紹如下幾種:

方式一:

  如下,是我們入門告訴大家的配置方式,可以看出config本質上是一個字典(內部繼承dict或者有__setitem__方法),通過給字典添加索引值對的方式可以實現配置,但是像這種方式把大幅的配置代碼寫在主要程式碼中,顯然不符合編程規範,所以不推薦這樣使用,當然flask也為我們其他辦法。

方式二:

  如下,將配置內容寫在py檔案中,通過讀取檔案的形式,應用程式啟動的時候回自動載入設定檔中的配置,注意一點的是,設定檔預設需要要放在程式root_path目錄,如果instance_relative_config為True,則就是instance_path目錄。

方式三:

  如下配置環境變數的方式,將設定檔配置成環境變數,然後通過app.config.from_envvar(‘環境變數名‘)讀取環境變數中的設定檔,其內部同樣還是調用from_pyfile方法,本質是一樣,同樣設定檔放置目錄同方式二。

方式四:

  通過將配置資訊配置在類中,按照app.config.from_object(“python類或類的路徑”)方式載入配置,這樣的方式不但可以將配置資訊和邏輯代碼分離,還可以做到將不同層級的配置進行分離,局部配置和全域配置分離,不同應用的配置也寫成不同的配置類,局部設定繼承全域配置,很靈活。為推薦的配置方式。

setting檔案樣本:

class BaseConfig(object):    ‘‘‘    放置全域配置    ‘‘‘    DB = ‘127.0.0.1‘    print("test BaseConfig")class TestConfig(BaseConfig):    ‘‘‘    放置局部配置    ‘‘‘    print("test TestConfig")class DevConfig(BaseConfig):    ‘‘‘    放置局部配置    ‘‘‘    print("test DevConfig")class ProConfig(BaseConfig):    ‘‘‘    放置局部配置    ‘‘‘    print("test ProConfig")

二、藍圖

  在之前的講解中我們都是將所有的應用程式寫在同一個py檔案之中,顯然這也不是很合理的吧。我們應該向django中一樣,將不同應用單獨分開,利用然後只用一個啟動程式檔案即可。在flask中可以用藍圖(Blueprint)實現,如下介紹中小型項目,藍圖為應用提供目錄劃分。

 

  mange.py檔案代碼執行個體:

import fcrm                                     #引用項目模組,會執行模組中的__init__.py檔案if __name__ == ‘__main__‘:    fcrm.app.run(port=8001)                     #app在fcrm模組中__init__.py檔案執行個體化

  __init__.py檔案代碼:

from flask import Flaskfrom .views import account                     #引入視圖檔案夾views下的account應用from .views import orderapp = Flask(__name__)print(app.root_path)app.register_blueprint(account.account)        #藍圖註冊應用app.register_blueprint(order.order)

  account應用代碼:

from flask import Blueprint,render_templateaccount = Blueprint(‘account‘,__name__)@account.route(‘/login‘)def login():    # return ‘Login‘    return render_template(‘login.html‘)

三、資料庫連接池

  不像django架構,flask架構沒有為我們提供內建的資料庫,因此我們只能自己引入諸如pymysql等模組,才能進行資料庫的操作,但是具體該怎麼做呢?可能我們可以直接在使用的地方串連資料庫就好,如下:

import pymysqlconn = pymysql.connect(.....)cursor = conn.cursor()cursor.execute(‘select * from tb where id > %s‘,[5,])result = cursor.fetchall()cursor.close()conn.close()print(result)

  但是像上述這種情況,每次請求反覆建立資料庫連接,串連數太多,顯然肯定不是很合理,生產中切記這樣串連資料庫。那我們是不是又會想到如下的解決辦法呢?提前建立串連,供各個視圖使用,不用重複建立資料庫連接。顯然這在單線程下是可行的,但是如果是多線程,我們就為了不使多個使用者操作資料庫操作資料庫,必須加鎖處理。但是這樣使得多線程失去意義。代碼如下:

import pymysqlimport threadingfrom threading import RLockLOCK = RLock()CONN = pymysql.connect(host=‘127.0.0.1‘,                       port=3306,                       user=‘root‘,                       password=‘123‘,                       database=‘pooldb‘,                       charset=‘utf8‘)def task(arg):    with LOCK:        cursor = CONN.cursor()        cursor.execute(‘select * from tb1‘)        result = cursor.fetchall()        cursor.close()        print(result)for i in range(10):    t = threading.Thread(target=task, args=(i,))    t.start()

  那我們 該怎麼做呢?我們就用到一個資料連線池的東西。DBUtils是Python的一個用於實現資料庫連接池的模組。安裝方式pip install DBUtils,但是在講資料庫連接池之前,我們先介紹一個本地線程的概念,本地線程其實就為每一個線程做唯一的標識,用於儲存此線程的資料,如下執行個體:

import threadingimport time# 本地線程對象local_values = threading.local()def func(num):    """    # 第一個線程進來,本地線程對象會為他建立一個    # 第二個線程進來,本地線程對象會為他建立一個    {        線程1的唯一標識:{name:1},        線程2的唯一標識:{name:2},    }    :param num:     :return:     """    local_values.name = num # 4    time.sleep(2)    #local_values.name,去local_values中根據自己的唯一標識作為key,擷取value中name對應的值    print(local_values.name, threading.current_thread().name)for i in range(5):    th = threading.Thread(target=func, args=(i,), name=‘線程%s‘ % i)    th.start()

資料庫連接池模式一:

  通過本地線程實現,為每個線程建立一個串連,線程即使調用了close方法,也不會關閉,只是把串連重新放到串連池,供自己線程再次使用。當線程終止時,串連自動關閉。如下:

from DBUtils.PersistentDB import PersistentDBimport pymysqlPOOL = PersistentDB(    creator=pymysql,       # 使用連結資料庫的模組    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‘‘‘ closeable=False,‘‘‘如果為False時, conn.close() 實際上被忽略,供下次使用,再線程關閉時,才會自動關閉連結。
如果為True時, conn.close()則關閉連結,那麼再次調用pool.connection時就會報錯,因為已
經真的關閉了串連(pool.steady_connection()可以擷取一個新的連結)‘‘‘ threadlocal=None, # 本線程獨享值得對象,用於儲存連結化物件,如果連結化物件被重設 host=‘127.0.0.1‘, port=3306, user=‘root‘, password=‘123‘, database=‘pooldb‘, charset=‘utf8‘)def func(): conn = POOL.connection() cursor = conn.cursor() cursor.execute(‘select * from tb1‘) result = cursor.fetchall() cursor.close() conn.close() #不是真的關閉,而是假的關閉。for i in range(10): t = threading.Thread(target=func) t.start()

資料庫連接池模式二:

  建立一批串連到串連池,供所有線程共用使用。PS:由於pymysql、MySQLdb等threadsafety值為1,所以該模式串連池中的線程會被所有線程共用。如下:

import timeimport pymysqlimport threadingfrom DBUtils.PooledDB import PooledDB, SharedDBConnectionPOOL = 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=‘123‘,    database=‘pooldb‘,    charset=‘utf8‘)def func():    # 檢測當前正在運行串連數的是否小於最大連結數,如果不小於則:等待或報raise TooManyConnections異常    # 否則    # 則優先去初始化時建立的連結中擷取連結 SteadyDBConnection。    # 然後將SteadyDBConnection對象封裝到PooledDedicatedDBConnection中並返回。    # 如果最開始建立的連結沒有連結,則去建立一個SteadyDBConnection對象,再封裝到PooledDedicatedDBConnection中並返回。    # 一旦關閉連結後,串連就返回到串連池讓後續線程繼續使用。    conn = POOL.connection()    cursor = conn.cursor()    cursor.execute(‘select * from tb1‘)    result = cursor.fetchall()    conn.close()func()

 

python之路_flask架構_flask架構基礎(2)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.