2010-09-06 39 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

相关问题