通过创建模块来简化数据库(psycopg2)的使用

fat*_*ake 3 python sql postgresql module psycopg2

首先,我要说我是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()
Run Code Online (Sandbox Code Playgroud)

这将打开与mydb数据库的连接,从表mytable中选择所有字段并打印它们,然后关闭连接。

我想做的就是将其中一些功能分解为一个模块,因为我需要在许多脚本中一遍又一遍地调用它们。对于此示例,理想情况下,我将有一个名为core的模块,其中包含三个功能:

  • core.db_init()-打开连接,由上面的前两行代码组成。
  • core.db_query(query)-执行所需的SQL查询,并由上述代码中的第三行组成。
  • core.db_close()-关闭连接并由最后两行组成。

我尝试过如下创建模块:

# 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()
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用此模块重新创建示例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()
Run Code Online (Sandbox Code Playgroud)

我什至不确定模块实际上是我想要的。我应该改为使用课程吗?再说一次,我对这一切都是新手。但是,如果有人可以帮助我找出更好的方法来完成此操作,我将非常感激。

Tor*_*xed 8

您的主要问题是,每个变量都限于您在其中编写的函数。
除非另有声明,否则:

def db_init():
    global conn
    conn = psycopg2....
Run Code Online (Sandbox Code Playgroud)

更好的方法是将其转换为类,一个基本的示例是:

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()
Run Code Online (Sandbox Code Playgroud)

现在,SELECT由于您正在使用,查询不会做太多事情cur.execute()
但是我故意这样做,以使代码与您编写的代码相似,但是您希望将其换出以返回值,但是如果调用预期返回值的查询等等。

您针对函数的方法将遇到“命名空间”问题,其中变量位于该函数的本地范围内,而其他函数通常无法访问它们。

取而代之的是,类范围的变量可以访问其自己的变量,并且没有限制。

您可以创建全局变量,然后在函数中将它们声明为全局变量,但我认为正如我在评论中提到的那样:

您想将其纳入一堂课。数据库是基于会话的实体,就像类是会话实体一样。通过类抽象将每个连接作为活动实体处理,否则cur和conn将成为作用域变量,您需要将它们处理到全局作用域中。