webpy架構:db模組分析

來源:互聯網
上載者:User

Webpy

是python的輕量級web架構

 

源碼位置(ubuntu10.10)
/usr/local/lib/python2.7/dist-packages/web/db.py

DB
 - MySQLDB
 - PostgresDB

定義DB是為了抽取出一個統一的API屏蔽掉不同資料庫API的差異

1,程式執行時,建立一個字典並註冊若干資料庫操作類(寫入字典)


class MySQLDB
class PostgresDB
...
_databases = {}
def register_database(name, clazz):
_databases[name] = clazz

register_database('mysql', MySQLDB)

2,調用函數database,傳入資料庫類型以及串連資訊,從字典_databases尋找操作類並執行個體化一個對象出來,這個就是我們代碼中的db

db = database(dbn='mysql', user='root', pw='dh6svp132e', db='test')

def database(dburl=None, **params):
dbn = params.pop('dbn')
if dbn in _databases:
return _databases[dbn](**params)


3, db對象的構建流程

class MySQLDB(DB):
def __init__(self, **keywords):#1
import MySQLdb as db
DB.__init__(self, db, keywords)

class DB:
def __init__(self, db_module, keywords):#2
self.db_module = db_module
self._ctx = threadeddict()
#基於線程儲存的字典,這個類被重載,不一定按照字典的文法使用

def _connect(self, keywords):
return self.db_module.connect(**keywords)

def _load_context(self, ctx):
ctx.db = self._connect(self.keywords)#5
#等價於 ctx['db'] = MySQLdb.connect(user='root', pw='dh6svp132e', db='test')

def _getctx(self):#4
#看看當前線程的字典裡有沒有定義_ctx['db']
if not self._ctx.get('db'):
self._load_context(self._ctx)
return self._ctx

ctx = property(_getctx)#3
#每次使用DB.ctx屬性時就執行_getctx

 

4, SQL執行

db.update("table",...)

class DB:
def _db_cursor(self):
return self.ctx.db.cursor()
#執行_getctx函數,如果線程之前有執行過SQL操作就會定義db,直接使用它,否則建立一個新的db,用db建立遊標對象

def _db_execute(self, cur, sql_query):
out = cur.execute(query, params)

def update(self, tables, where, vars=None, _test=False, **values):
db_cursor = self._db_cursor()
self._db_execute(db_cursor, query)

總結:
db 是屬於進程的全域變數,雖然各個線程都會使用db操作資料庫,但是db卻是安全的,因為db._ctx對象是一個基於線程儲存的字典,線程A在操作資料庫 時需要一個資料庫操作對象,它會去db._ctx裡檢查有沒有屬於自己這個線程的db,有就使用它,沒有就建立一個,並以字串'db'作為key,建立 的連線物件作為value存進db._ctx,因為這個key只線上程A裡可見,線程B需要操作資料庫的時候也會自己建立一個資料庫連接對象,因此不同線 程的資料庫操作就被隔離開(很像單例模式)

推測:
webpy是MVC架構,使用者的請求都可以映射到一個函數上,而 每次使用者的一個請求都啟了一個新的線程來執行,由這個線程來調用這個被映射的函數,而這個函數裡可能寫了大量的資料庫操作,體現在代碼裡就是很多的 db.insert(...),db.update(...),db.delete(...)這種操作,只有執行第一個函數調用的時候,我們才建立一個真 正的資料庫連接對象,之後的函數調用都是複用這個串連,等這個函數執行完畢,線程銷毀或者迴歸到線程池,如果線程銷毀則_ctx.db也會銷毀,如果是回 歸線程池,則必然有_ctx.db.close(),然後.ctx.clearAll()的操作

 

webpy的threadeddict實現
import threading
class ThreadedDict(threadlocal):
_instances = set()

def __init__(self):
ThreadedDict._instances.add(self)

threadeddict = ThreadedDict

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.