2010-09-06 22 views
1

如果我有一個獨立的類爲我的數據庫調用,我創建了另一個數據庫層的實現,但說一個不同的數據存儲。如何在python中換出特定的數據庫實現?

有沒有辦法對我來說,完全地換出,而無需更改代碼配發的實施?

即我正在開始一個項目,所以我可以正確設計事情以實現這一目標。

注:我會用這種模式對於網站的其他部分也不僅僅是DB層所以它不是真正具體到只有DB層。

+1

你看過使用對象關係映射器,如SQLAlchemy嗎? http://www.sqlalchemy.org/ – 2010-09-06 23:54:00

回答

2

只要兩個模塊實現完全相同的接口(類名稱相同,方法和其他屬性,使用相同的名稱和簽名功能......),你可以選擇一個或另一個的時候你應用程序正在啓動,例如基於某個配置文件,並以固定名稱導入所選應用程序。然後,所有其他應用程序可以使用該固定名稱,並在啓動代碼的基礎上,對開始時可能已經完成的任何惡意軟件不知情。

例如,考慮一個簡化的情況:

# english.py 
def greet(): return 'Hello!' 

# italian.py 
def greet(): return 'Ciao!' 

# french.py 
def greet(): return 'Salut!' 

# config.py 
langname = 'italian' 

# startit.py 
import config 
import sys 
lang = __import__(config.langname) 
sys.modules['lang'] = lang 

現在,應用程序的所有剩下的就只是import lang,並且將在該名稱下獲得italian模塊,因此,呼籲lang.greet()時,將得到字符串'Ciao!'

當然,在現實生活中,你將有多個模塊,每個模塊具有多種功能,類和諸如此類的東西,但總的原則留下非常相似。只取約模塊特別小心合格名稱(如foo.bar),即,其必須駐留在一個包(在此情況下,foo)模塊。對於這些,你不能只用__import__的返回值,但必須使用一個稍微更迂迴的辦法,如:

import sys 
def importanyasname(actualname, fakename): 
    __import__(actualname) 
    sys.modules[fakename] = sys.modules[actualname] 

就是忽略__import__的返回值,和值正確到達剩下的(實際名稱爲重點)的sys.modules字典 - 是你所尋求的模塊對象,你可以設置回sys.modules與「假名字」,通過該應用程序的所有其餘部分將能夠隨時隨地導入。

+0

感謝alex,稍微偏離主題,你更喜歡在像apache這樣的web服務器上運行python,還是隻是在不同的端口上運行'paster',並讓haproxy在其中分佈?似乎高交通商店正在使用後者。 – Blankman 2010-09-07 16:01:26

+0

你會如何使用'importanyasname'?對於那裏發生的事情一點困惑。 – Blankman 2010-09-07 16:02:23

+0

@Blankman,我通常處於與您設想的不同狀態(編碼在Google生產系統上運行,無論是在App Engine還是其他平臺上運行),所以我的經驗並不直接適用(對於個人/開源用途,我使用的是東西像ligthttpd,龍捲風,twisted自己的服務器,等等 - 如果必須的話,當然是apache ;-)。如果需要支持真實名稱爲限定名稱的模塊,則應該調用'importasanyname',而不是將兩個語句放在'startit.py'末尾的前一個片段中。 – 2010-09-07 21:16:20

相關問題