Simplifier l'utilisation de la base de données (psycopg2) en créant un module

Permettez-moi de commencer par dire que je suis assez nouveau à Python et je m'excuse si ce n'est pas l'endroit approprié pour cette question.

j'utilise le module psycopg2 pour manipuler une base de données PostgreSQL. L'usage général ressemblerait à quelque chose comme ceci:

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

ceci ouvrira une connexion à la base de données mydb , sélectionnez tous les champs de la table mytable et les imprimer, puis fermer la connexion.

Ce que je voudrais faire est de factoriser certaines de ces fonctions dans un module, car j'ai besoin de les appeler reprises tout au long de plusieurs scripts. Pour cet exemple, idéalement j'aurais un module nommé core qui contient trois fonctions:

  • de base.db_init() - qui ouvre la connexion et se compose des deux premières lignes de code ci-dessus.
  • de base.db_query (requête) - qui exécute la requête SQL désirée et se compose de la troisième ligne dans le code ci-dessus.
  • de base.db_close () qui ferme la connexion et se compose des deux dernières lignes.

j'ai essayé de créer un module comme suit:

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

mais j'obtiens des erreurs d'espace de noms quand j'essaie de recréer L'exemple 1 en utilisant ce module:

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

je suis Je ne suis même pas sûr qu'un module soit vraiment ce que je veux. Devrais-je utiliser un cours à la place? Encore une fois, je suis très nouveau à tout cela. Mais si quelqu'un pouvait m'aider à trouver une meilleure façon pour ce faire, je vous serais très reconnaissant.

2
demandé sur fattybake 2016-05-27 19:17:55

2 réponses

votre problème principal, est que chaque variable est limitée à la fonction dans laquelle vous l'avez écrite.

À moins qu'il n'en soit déclaré autrement:

def db_init():
    global conn
    conn = psycopg2....

une meilleure approche serait de transformer cela en une classe, un exemple de base serait:

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

maintenant, la requête SELECT ne fera pas grand chose puisque vous utilisez cur.execute() .

Mais j'ai gardé exprès pour avoir un code similaire à ce que vous écrit, vous voudrez l'échanger pour retourner les valeurs cependant si l'appel d'une requête qui est censé retourner une valeur et ainsi de suite.

votre approche qui est axée sur les fonctions aura des problèmes" namespace " où les variables vivent dans une portée locale de cette fonction et là pour d'autres fonctions ne peuvent normalement pas y accéder.

au lieu de cela, les variables scoped de classe peuvent accéder à ses propres variables et est là pour pas aussi limité hors de la boîte.

vous pourriez faire des variables globales et les déclarer comme globales dans les fonctions, mais je pense comme je l'ai mentionné dans un commentaire:

vous voudriez en faire une classe. Une base de données est une entité basée sur une session tout comme les classes sont des entités de session. Traitez chaque connexion comme une entité vivante en l'abstrayant par classe, sinon cur et conn deviendront des variables scoped et vous devez les travailler dans la portée globale.

2
répondu Torxed 2016-05-27 17:06:18

vous pouvez le faire de la façon que vous voulez - bien que je considérerais utiliser sqlalchemy ou un autre module pour manipuler ces pièces pour vous.

le code que vous avez collé ne fonctionne pas parce que cursor n'est pas défini dans vos autres méthodes.

envisager de le faire en un seul appel - par exemple:

# 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

Notez que ce n'est pas optimal, et si vous faites beaucoup de petites requêtes meurtre de connexion pour chacun n'est pas le la meilleure idée.

0
répondu Daniel 2016-05-27 17:04:17