在许多python模块中提供数据库连接的正确方法

时间:2011-07-26 11:59:42

标签: python mysql

我想在许多python模块中创建一个数据库对象。

对于相关的示例,我创建了globl.py:

DOCS_ROOT="c:\docs" ## as an example
SOLR_BASE="http://localhost:8636/solr/"

需要它的任何其他模块都可以执行

from globl import DOCS_ROOT

现在抛开这个例子,我想对数据库连接对象做同样的事情,在多个模块中共享它们

import MySQLdb
conn = MySQLdb.connect (host="localhost"...)
cursor = conn.cursor()

我在翻译上尝试了这个:

from globl import cursor

它似乎有效。但我怀疑这会导致每次从中导入时执行相同的模块。这是正确的方法吗?

3 个答案:

答案 0 :(得分:29)

即使导入多次没有运行代码,这绝对不是正确的方法。

您应该隐藏在函数后面获取连接或光标的过程。然后,您可以使用SingletonObject Pool设计模式实现此功能。

所以它会是这样的:

<强> db.py:

_connection = None

def get_connection():
    global _connection
    if not _connection:
        _connection = MySQLdb.connect(host="localhost"...)
    return _connection

# List of stuff accessible to importers of this module. Just in case
__all__ = [ 'getConnection' ]

## Edit: actually you can still refer to db._connection
##         if you know that's the name of the variable.
## It's just left out from enumeration if you inspect the module

<强> someothermodule.py:

import db
conn = db.get_connection() # This will always return the same object

顺便说一下,根据你在做什么,分享可能不是一个好主意 您的连接对象,而不是每次需要时创建一个新对象。

但是,这就是为什么你想编写一个get_connection()方法,从代码的其余部分中抽象出这些问题。

答案 1 :(得分:4)

你怀疑是错误的。代码只会被执行一次 - 后续导入只是通过sys.modules引用模块,而不是重新运行它。

(请注意,只要你总是使用相同的路径导入模块就是这种情况 - 如果你在一个地方做from globl import cursor,而在另一个地方做from my.fullyqualified.project.global import cursor,你可能会发现代码重新执行。)

编辑添加,如S.Lott在评论中所说,这是处理全局对象的一种非常好的方法。

答案 2 :(得分:1)

我认为丹尼尔已经回答了这个问题,而我想补充一些关于你想要分享的光标对象的评论。

以这种方式共享游标对象通常不是一个好主意。当然这取决于你的程序是什么,但作为一般解决方案,我建议你将这个光标对象隐藏在生成游标的“工厂”后面。基本上,您可以创建方法cursor()get_cursor(),而不是将光标作为全局变量。主要的好处(但不是唯一的) - 你可以隐藏这个“工厂”背后的更复杂的逻辑 - 池连接,自动重新连接以防连接断开等等。即使你不喜欢如果你现在就开始使用这种方法,那么以后就可以很容易地添加它。现在你可以保持这个函数实现像return _cursor一样简单。

是的,模块本身只会导入一次。