Good practice sharing resources between modules?

bgusach picture bgusach · Nov 30, 2012 · Viewed 7.8k times · Source

I am reorganizing my code and therefore creating new namespaces. I'm changing "static" classes (classes with @staticmethod in each method) for modules. This is the way to go, right?

The problem is that I have doubts on how to share the resources between these modules.

Let's say I had a module from which I was doing all connections to database, and of course all classes/methods were sharing the variable which stored the DB cursor (I'm using SQLite). Now, in different modules, they also have to share the cursor.

Graphical representation of dependences

So, my ideas:

  • Declare the global variable in each module. But globals are evil, eat children and steal our jobs. So I don't know if this is the way to go.

    '''Sub Module 1'''
    
    global database_cursor
    
  • Import the "father" database_module with the original database_cursor and use something like this:

    '''Sub Module 1'''
    
    db_cursor = database_module.database_cursor
    

This second looks fine in this case, but I think in many cases will lead to recursive imports, which I guess it´s something to avoid.

Answer

RickyA picture RickyA · Nov 30, 2012

Your second method is the way to go. Python imports are singleton by nature. When a module is imported multiple times it is only executed the first time. Subsequent imports fetch the module object instance from the globals. More on that here.

shared.py:

class Shared:
    def __init__(self):
        print("Init shared")

    def do_stuff(self, from_mod):
        print("Do stuff from {0}. I am instance {1}".format(from_mod, self))

shared = Shared()

foo.py

import shared

shared.shared.do_stuff("foo")

bar.py

import foo
import shared

shared.shared.do_stuff("bar")

If we execute bar.py we get:

>>> Init shared
>>> Do stuff from foo. I am instance <shared.Shared instance at 0x10046df38>
>>> Do stuff from bar. I am instance <shared.Shared instance at 0x10046df38>

So in your case you can reference database_module from anywhere you want and it gets initialized only once, therefore effectively sharing your connection.