Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/307.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/64.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使DB连接跨多个python模块可用的正确方法_Python_Mysql - Fatal编程技术网

使DB连接跨多个python模块可用的正确方法

使DB连接跨多个python模块可用的正确方法,python,mysql,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.connec

我想在许多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

这似乎奏效了。但我怀疑这将导致每次从中导入时执行相同的模块。那么这是正确的方法吗?

你猜错了。代码只执行一次-后续导入仅通过
sys.modules
引用模块,不重新运行

(请注意,只要始终使用相同的路径导入模块,就会出现这种情况-如果在一个位置从全局导入光标执行
,在另一个位置从my.fullyqualified.project.global导入光标执行
,您可能会发现代码被重新执行。)


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

我认为Daniel已经回答了这个问题,而我想添加一些关于您想要共享的游标对象的评论

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


当然,模块本身只会导入一次

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

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

所以应该是这样的:

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
import db
conn = db.get_connection() # This will always return the same object
someothermodule.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
import db
conn = db.get_connection() # This will always return the same object
顺便说一句,根据你正在做什么,分享可能不是一个好主意 连接对象,而不是每次需要时都创建一个新的连接对象


但是,这就是为什么您希望编写一个
get_connection()
方法,以便在代码的其余部分中从这些问题中抽象出来。

关于“这是正确的方法吗?”我认为您应该指出,这样的全局模块从长远来看效果非常好。这也是一个很好的答案。如果我运行这段代码,我会得到UnboundLocalError:之前引用的局部变量“\u connection”assignment@Jim没错。这是一个仓促的例子。我添加了一行带有
global\u connection
。使用
\uuuu all\uuuu
还有一个很好的特性,即使用
import*
表示将要导入命名空间的内容。并不是说如果你能帮上忙,你就应该使用
import*
。:-)我以后会提到这一点。这是一种在简单界面后面制作复杂内容的好方法。