我想在许多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
它似乎有效。但我怀疑这会导致每次从中导入时执行相同的模块。这是正确的方法吗?
答案 0 :(得分:29)
即使导入多次没有运行代码,这绝对不是正确的方法。
您应该隐藏在函数后面获取连接或光标的过程。然后,您可以使用Singleton或Object 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
一样简单。
是的,模块本身只会导入一次。