【问题标题】:Simplify database (psycopg2) usage by creating a module通过创建模块来简化数据库 (psycopg2) 的使用
【发布时间】:2016-09-26 01:41:40
【问题描述】:

让我先说我对 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 的模块,它包含三个功能:

  • 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()

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

我什至不确定模块是否真的是我想要的。我应该改用一个类吗?再说一次,我对这一切都很陌生。但如果有人能帮助我找出更好的方法来做到这一点,我将不胜感激。

【问题讨论】:

  • 写得很好的问题顺便说一句,有你尝试过的一切,你想要的行为是什么,大致是一个实际的错误。也欢迎使用 StackOverflow,特别欢迎使用 Python :) 如果下面给出的任何答案都解决了您的需求,请不要忘记将问题标记为“已回答”,这样它就不会出现在一堆未回答的问题中。

标签: python sql postgresql module psycopg2


【解决方案1】:

您的主要问题是每个变量都仅限于您编写的函数。
除非另有声明:

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 将成为作用域变量,您需要将它们放入全局作用域。

【讨论】:

  • 非常感谢!我最终几乎一字不差地使用了你的课堂方法。我真的很感谢你花时间回答我的问题,即使它相当愚蠢。感谢您的热烈欢迎:)
  • @fattybake 不客气,我很高兴。像您这样友好的人值得花时间在给出的答案上多花一分钟时间:)继续努力,祝您工作顺利!
【解决方案2】:

您可以按照自己的方式进行操作 - 尽管我会考虑使用 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

请注意,这不是最佳选择,如果您正在执行大量小查询,则杀死每个查询的连接不是最好的主意。

【讨论】:

  • 感谢您的回答!我很感激你试图让它尽可能地与我的方法相似。你绝对是正确的,因为它会在我每次尝试做任何事情时打开和关闭连接。我最终选择了 Torxed 的解决方案,因为这是我想要做的,尽管我并不确切知道我需要什么。
  • 我投了赞成票,尽管在运行周期中您不太可能只需要一个查询。
猜你喜欢
  • 2013-10-25
  • 2023-02-24
  • 1970-01-01
  • 2022-06-18
  • 2020-10-20
  • 2017-05-17
  • 2012-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多