J'ai créé une bibliothèque en Python qui contient des fonctions pour accéder à une base de données. Il s'agit d'une bibliothèque d'encapsulation autour d'une base de données d'applications tierces, écrite du fait que l'application tierce n'offre pas une API décente. Maintenant, je laissais à l'origine chaque fonction ouvrir une connexion à la base de données pendant la durée de l'appel de fonction, ce qui était OK, jusqu'à ce que ma logique de programme utilise des appels imbriqués vers les fonctions où j'appellerais alors une fonction particulière plusieurs milliers de fois. Ce n'était pas très performant. Le profilage a montré que la surcharge était dans la configuration de la connexion à la base de données - une fois par appel de fonction. J'ai donc déplacé la connexion ouverte de la ou des fonctions vers le module lui-même, afin que la connexion à la base de données soit ouverte lors de l'importation du module de bibliothèque. Cela m'a donné une performance acceptable.
Maintenant, j'ai deux questions à ce sujet. Premièrement, dois-je m'inquiéter de ne plus fermer explicitement la connexion à la base de données et comment pourrais-je le faire explicitement avec cette configuration? Deuxièmement, est-ce que ce que j'ai fait se rapproche du domaine des bonnes pratiques et comment pourrais-je autrement aborder cela?
openConn
fonction et demandez à l'utilisateur de la transmettre à chaque fonction qu'il appelle, de cette façon, il peut étendre la connexion dans unewith
instruction ou autreRéponses:
Cela dépend vraiment de la bibliothèque que vous utilisez. Certains d'entre eux pourraient fermer la connexion par eux-mêmes (Remarque: j'ai vérifié la bibliothèque sqlite3 intégrée, et ce n'est pas le cas). Python appellera un destructeur lorsqu'un objet sort de la portée, et ces bibliothèques peuvent implémenter un destructeur qui ferme les connexions avec élégance.
Mais ce n'est peut-être pas le cas! Je recommanderais, comme d'autres l'ont fait dans les commentaires, de l'envelopper dans un objet.
Cela instanciera votre connexion à la base de données au début et la fermera lorsque l'endroit où votre objet a été instancié devient hors de portée. Remarque: Si vous instanciez cet objet au niveau du module, il persistera pour l'ensemble de votre application. À moins que cela ne soit prévu, je suggérerais de séparer vos fonctions de base de données des fonctions non liées à la base de données.
Heureusement, le python a standardisé l'API de base de données , donc cela fonctionnera avec toutes les bases de données conformes pour vous :)
la source
self
endef query(self,
?db.query('SELECT ...', var)
et à mesure qu'il se plaignait d'avoir besoin d'un troisième argument.MyDB
objet:db = MyDB(); db.query('select...', var)
ResourceWarning: unclosed <socket.socket...
lors de la gestion des connexions à la base de données, il y a deux choses à se soucier:
éviter les instanciations de connexions multiples, laisser chaque fonction ouvrir une connexion à une base de données est considéré comme une mauvaise pratique, étant donné le nombre limité de sessions de base de données, vous manqueriez de sessions; au moins votre solution ne serait pas évolutive, utilisez plutôt un modèle singleton, votre classe ne serait instanciée qu'une seule fois, pour plus d'informations sur ce modèle, voir le lien
la fermeture de la connexion à la sortie de l'application, disons que vous ne l'avez pas fait, et que vous avez au moins une douzaine d'instances de l'application en cours d'exécution faisant de même, au début, tout irait bien, mais vous manqueriez de sessions de base de données, et le seul correctif serait de redémarrer le serveur de base de données, ce qui n'est pas une bonne chose pour une application en direct, donc utilisez la même connexion chaque fois que possible.
pour solidifier tous ces concepts, voir l'exemple suivant qui enveloppe psycopg2
la source
if Database._instance is None: NameError: name 'Database' is not defined
. Je ne peux pas comprendre ce queDatabase
c'est et comment je pourrais y remédier.Postgres.query(Postgres(), some_sql_query)
dans unewhile
boucle, ouvrirait-elle et fermerait-elle toujours la connexion à chaque itération, ou la maintiendrait-elle ouverte pendant toute la durée de lawhile
boucle jusqu'à la fin du programme?query()
fonction, mais il semble qu'il y ait un problème avec mon code lorsque j'exécute mon application en "parallèle". J'ai fait une question distincte à ce sujet: softwareengineering.stackexchange.com/questions/399582/…Il serait intéressant d'offrir des capacités de gestionnaire de contexte pour vos objets. Cela signifie que vous pouvez écrire un code comme celui-ci:
Cela vous offrira un moyen pratique de fermer automatiquement la connexion à la base de données en appelant la classe à l'aide de l'instruction with:
la source
Beaucoup de temps pour y penser. Aujourd'hui, j'ai trouvé le chemin. je ne sais pas c'est la meilleure façon. vous créez un fichier avec le nom: conn.py et l'enregistrez dans le dossier /usr/local/lib/python3.5/site-packages/conn/. J'utilise freebsd et c'est le chemin de mon dossier site-packages. dans mon conn.py: conn = "dbname = omnivore user = postgres password = 12345678"
`` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` `` ` et dans le script je veux appeler connection, j'écris:
importation psycopg2 importation psycopg2.extras importation psycopg2.extensions
depuis conn import conn conn: conn = psycopg2.connect (conn.conn) sauf: page = "Impossible d'accéder à la base de données"
cur = conn.cursor ()
et bla bla ...
j'espère que c'est utile
la source