Ricky Levi
Ricky Levi

Reputation: 7997

Why the variable is being shared in some Classes but not others?

I have an issue where my Classes keep creating new DB connections, and I'm trying to understand what am I doing wrong... this is my structure:

index.py
 |_ a/const.py    ( not a Class, just several functions )
      db = None

      def get_connection():
         global db

         if not db:    
           db = created_new_connection()
           print "New connection has been created"
         else:
           print "Connection already exists"

         return db

 |_ a/group.py   ( import const, Class )
 |_ a/user.py    ( import const, Class )

"index.py" imports "const" and another module that later uses "group" and "user"

When I run index.py, I get:

group.py "New connection has been created"
user.py "New connection has been created"

So for the test, I tried creating the connection in the "index.py" instead, but now I get:

index.py "New connection has been created"
group.py run func1() "Connection already exists"
group.py run func2() "Connection already exists"
user.py "New connection has been created"

Now - I'm confused. both "group" and "user" are written almost the exact same way. how is it that when "group" run "get_connection()" it works as expected ( already exists ) and later when "user" run "get_connection()" it creates a new connection ....

What's interesting ( to me ) is that when I created files ( a,b,c,d ) in the same directories ( to keep structure ) and imported "c.py" in all files, then "a" created the connection, but "b and d" did not create a new connection, they used the one that is still open.... ( which is what I expect )

Any ideas ? thanks in advance ...

Upvotes: 0

Views: 90

Answers (2)

gitaarik
gitaarik

Reputation: 46320

Instead of using a global variable, you can also consider using a "Borg" class. This is the Python alternative to a singleton class.

database.py

class Database:

    __shared_state = {}
    db = None

    def __init__(self):
        self.__dict__ = self.__shared_state

    def get_connection(self):

        if not self.db:
            self.db = self.create_new_connection()
            print "New connection has been created"
        else:
            print "Connection already exists"

        return self.db

    def create_new_connection(self):
        # create and return new connection

Then import this class like from database import Database and get your connection with Database().get_connection().

Upvotes: 0

BartoszKP
BartoszKP

Reputation: 35891

Try changing it to this:

def get_connection():
    global db

    if not db:    
        db = created_new_connection()
        print "New connection has been created"
    else:
        print "Connection already exists"

    return db

If you have this, the only possibility for the function to enter the first block for the second time is that created_new_connection() function returns something that evaluates to False (e.g. None or an empty str, or an empty list, ...).

Alternatively, you may experience a situation when Python loads a module twice, as explained here: basically if you import a module using different relative paths Python will treat them as different modules, and load them twice. A suggested solution from this blog post is to always load modules using their top-level paths.

Upvotes: 1

Related Questions