Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I have created a library in Python that contains functions for accessing a database. This is a wrapper library around a third party application database, written due to the fact that the third party application does not offer a decent API. Now I originally let each function open a database connection for the duration of the function call which was OK, until my program logic used nested calls to the functions where I would then be calling a particular function a few thousand times. This wasn't very performant. Profiling this showed that the overhead was in the database connection setup - once per function call. So I moved the open connection from within the function(s) to the module itself, so that the database connection would be opened when the library module was imported. This gave me an acceptable performance.

Now I have two questions regarding this. Firstly, do I need to be concerned that I am no longer explicitly closing the database connection and how could I do it explicitly with this set-up? Secondly, does what I have done fall anywhere close to the realm of good practice and how might I otherwise approach this?

share|improve this question
1  
Provide an openConn function and make the user pass it to each function they call, that way they can scope the connection in a with statement or whatever – jozefg Jun 5 '13 at 10:28
1  
I agree with jozfeg, consider a creating a class that opens the db connection within the constructor, and that closes the connection at exit – Nick Burns Jun 5 '13 at 10:49
    
See eli.thegreenplace.net/2009/06/12/… – coredump Sep 6 '15 at 11:34
up vote 9 down vote accepted

It really depends on the library you're using. Some of them could be closing the connection on their own (Note: I checked the builtin sqlite3 library, and it does not). Python will call a destructor when an object goes out of scope, and these libraries might implement a destructor that closes the connections gracefully.

However, that might not be the case! I would recommend, as others have in the comments, to wrap it in an object.

class MyDB(object):
    _db_connection = None
    _db_cur = None

    def __init__(self):
        self._db_connection = db_module.connect('host', 'user', 'password', 'db')
        self._db_cur = self._db_connection.cursor()

    def query(self, query, params):
        return self._db_cur.execute(query, params)

    def __del__(self):
        self._db_connection.close()

This will instantiate your database connection at the start, and close it when the place your object was instantiated falls out of scope. Note: If you instantiate this object at the module level, it will persist for your entire application. Unless this is intended, I would suggest separating your database functions from the non-database functions.

Luckily, python has standardized the Database API, so this will work with all of the compliant DBs for you :)

share|improve this answer
    
How do you avoid that self in def query(self,? – samayo Nov 9 '15 at 19:08
1  
define avoid? Self is what defines that as an instance method, rather than a class method. I guess you could create the database as a static property on the class, and then only use class methods (no self needed anywhere), but then the database would be global to the class, not just the individual instantiation of it. – Travis Nov 9 '15 at 22:46
    
Yeah, because I tried to use your example to make a simple query as db.query('SELECT ...', var) and it complained about needing a third argument. – samayo Nov 9 '15 at 23:30

A long time to think about this. To day , i found the way . i don't know it is the best way. you create a file with the name: conn.py , and save it in /usr/local/lib/python3.5/site-packages/conn/ folder. I use freebsd and this is the path of my site-packages folder. in my conn.py: conn = "dbname=omnivore user=postgres password=12345678"

`````````````````````````````````````````````````` and in the script i want to call connection ,i write:

import psycopg2 import psycopg2.extras import psycopg2.extensions

from conn import conn try: conn = psycopg2.connect(conn.conn) except: page = "Can not access database"

cur = conn.cursor()

and blah blah....

i hope this useful

share|improve this answer

protected by gnat 13 hours ago

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.