让我先说一下我是Python的新手,如果这不是这个问题的合适位置,我会道歉。
我正在使用 psycopg2 模块来操作PostgreSQL数据库。一般用法看起来像这样:
# Example 1
import psycopg2
conn = psycopg2.connect(database="mydb", user="postgres")
cur = conn.cursor()
cur.execute ("SELECT * FROM mytable;")
rows = cur.fetchall()
for i, row in enumerate(rows):
print "Row", i, "value = ", row
cur.close()
conn.close()
这将打开与 mydb 数据库的连接,从表 mytable 中选择所有字段并打印它们,然后关闭连接。
我想要做的是将这些功能中的一部分分解为一个模块,因为我需要在许多脚本中反复调用它们。对于这个例子,理想情况下我会有一个名为 core 的模块,它包含三个函数:
我尝试按如下方式创建模块:
# Module core.py
import psycopg2
def db_init():
conn = psycopg2.connect(database="mydb", user="postgres")
cur = conn.cursor()
def db_query(query):
cur.execute(query)
def db_close():
cur.close()
conn.close()
但是当我尝试使用此模块重新创建示例1时,我得到命名空间错误:
# Example 2
import core
core.db_init()
core.db_query("SELECT * FROM mytable;")
rows = cur.fetchall()
for i, row in enumerate(rows):
print "Row", i, "value = ", row
core.db_close()
我甚至不确定模块实际上是我想要的。我应该使用课吗?再说一遍,我对这一切都很陌生。但如果有人能帮助我找到更好的方法,我会非常感激。
答案 0 :(得分:5)
您的主要问题是,每个变量仅限于您编写的功能 除非另有声明:
def db_init():
global conn
conn = psycopg2....
更好的方法是将其转换为类,一个基本的例子是:
import psycopg2
class MyDatabase():
def __init__(self, db="mydb", user="postgres"):
self.conn = psycopg2.connect(database=db, user=user)
self.cur = self.conn.cursor()
def query(self, query):
self.cur.execute(query)
def close(self):
self.cur.close()
self.conn.close()
db = MyDatabase()
db.query("SELECT * FROM table;")
db.close()
现在,SELECT
查询在您使用cur.execute()
后不会做太多事情。
但我保留这个目的是为了保持代码与你写的代码类似,你想要交换它来返回值,但是如果调用一个预期会返回值的查询等等。
专注于功能的方法将具有"命名空间"变量存在于该函数的局部范围内的问题以及其他函数通常无法访问它们。
相反,类范围的变量可以访问它自己的变量,而不是开箱即用的限制。
你可以创建全局变量并在函数中将它们声明为全局变量,但我认为正如我在评论中提到的那样:
你想把它变成一个班级。数据库是基于会话的实体,就像类是会话实体一样。通过类抽象将每个连接作为一个生命实体处理,否则cur和conn将成为范围变量,您需要将它们用于全局范围。
答案 1 :(得分:1)
您可以按照自己的方式进行操作 - 尽管我会考虑使用sqlalchemy
或其他模块为您处理这些部分。
您粘贴的代码不起作用,因为您的其他方法中未定义cursor
。
考虑在一次通话中进行 - 例如:
# Module core.py
import psycopg2
def execute_query(query):
conn = psycopg2.connect(database="mydb", user="postgres")
cur = conn.cursor()
results = cur.execute(query)
cur.close()
conn.close()
return results
请注意,这不是最佳选择,如果您正在进行大量小型查询,则查找每个查询的连接并不是最佳选择。