best way to share an instance of a class among modules?

Discussion in 'Python' started by CM, Feb 6, 2013.

  1. CM

    CM Guest

    I have recently moved all my SQLite3 database-related functions into a
    class, DatabaseAccess, that lives in a "utilities" module. When the
    application loads, the namespace of the instance of the class is
    populated with two different cursors for two different databases the
    whole application needs to use. One of those cursors always refers to
    a connection to the same database, but the other cursor can change
    which database it refers to; in this regard, the namespace of the
    DatabaseAccess class instance holds a "state" (which is which database
    the one cursor currently refers to)

    I have a number of modules that all need to use those two cursors.
    However, if I import the utilities module and create a new instance of
    the DatabasesAccess() in each of all the various modules, obviously
    each new instance doesn't have the same namespace as the first
    instance, and so doesn't have the *same* two cursors.

    I can think of a few ways to pass the DatabaseAcess instance around to
    the various modules, but all of them seem like repeating myself and
    clunky. What's the "best" (most Pythonic, simplest) way for a number
    of modules to all share the same instance of my DatabaseAccess class?

    Thanks,
    Che
     
    CM, Feb 6, 2013
    #1
    1. Advertising

  2. CM

    Terry Reedy Guest

    On 2/5/2013 11:40 PM, CM wrote:
    > I have recently moved all my SQLite3 database-related functions into a
    > class, DatabaseAccess, that lives in a "utilities" module. When the
    > application loads, the namespace of the instance of the class is
    > populated with two different cursors for two different databases the
    > whole application needs to use. One of those cursors always refers to
    > a connection to the same database, but the other cursor can change
    > which database it refers to; in this regard, the namespace of the
    > DatabaseAccess class instance holds a "state" (which is which database
    > the one cursor currently refers to)
    >
    > I have a number of modules that all need to use those two cursors.
    > However, if I import the utilities module and create a new instance of
    > the DatabasesAccess() in each of all the various modules, obviously
    > each new instance doesn't have the same namespace as the first
    > instance, and so doesn't have the *same* two cursors.
    >
    > I can think of a few ways to pass the DatabaseAcess instance around to
    > the various modules, but all of them seem like repeating myself and
    > clunky. What's the "best" (most Pythonic, simplest) way for a number
    > of modules to all share the same instance of my DatabaseAccess class?


    Attach the instance of the class to the utilities module that clients
    import. It does not matter if the code is in the utilities module itself
    or in one of the importing modules (possibly the first).

    # in module
    shared_cursor =

    # in importer
    import utilities
    utilities.shared_cursor = DatabaseAccess(args)

    Module attributes are mutable and can be set from elsewhere.

    --
    Terry Jan Reedy
     
    Terry Reedy, Feb 6, 2013
    #2
    1. Advertising

  3. CM

    CM Guest

    On Feb 6, 12:04 am, Terry Reedy <> wrote:
    > On 2/5/2013 11:40 PM, CM wrote:
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > > I have recently moved all my SQLite3 database-related functions into a
    > > class, DatabaseAccess, that lives in a "utilities" module.  When the
    > > application loads, the namespace of the instance of the class is
    > > populated with two different cursors for two different databases the
    > > whole application needs to use.  One of those cursors always refers to
    > > a connection to the same database, but the other cursor can change
    > > which database it refers to; in this regard, the namespace of the
    > > DatabaseAccess class instance holds a "state" (which is which database
    > > the one cursor currently refers to)

    >
    > > I have a number of modules that all need to use those two cursors.
    > > However, if I import the utilities module and create a new instance of
    > > the DatabasesAccess() in each of all the various modules, obviously
    > > each new instance doesn't have the same namespace as the first
    > > instance, and so doesn't have the *same* two cursors.

    >
    > > I can think of a few ways to pass the DatabaseAcess instance around to
    > > the various modules, but all of them seem like repeating myself and
    > > clunky.  What's the "best" (most Pythonic, simplest) way for a number
    > > of modules to all share the same instance of my DatabaseAccess class?

    >
    > Attach the instance of the class to the utilities module that clients
    > import. It does not matter if the code is in the utilities module itself
    > or in one of the importing modules (possibly the first).
    >
    > # in module
    > shared_cursor =
    >
    > # in importer
    > import utilities
    > utilities.shared_cursor = DatabaseAccess(args)
    >
    > Module attributes are mutable and can be set from elsewhere.
    >
    > --
    > Terry Jan Reedy


    Thank you. But, I'm sorry, I'm not following this enough to get it to
    work. Shouldn't it be a little more like this:

    # in utilities module
    shared_cursor = DatabaseAccess_instance #but how? see my question
    below...

    # in importer
    import utilities
    self.shared_cursor = utilities.shared_cursor ("self" is here to make
    cursor available to all functions in importer

    My only problem, then, is I create the shared_cursor from within a
    function within the instance of DatabaseAccess(). How then do I pass
    it from within the function's namespace to the module's namespace so
    that I can do that first line?
     
    CM, Feb 6, 2013
    #3
  4. On 02/06/2013 03:41 PM, CM wrote:
    > Thank you. But, I'm sorry, I'm not following this enough to get it to
    > work. Shouldn't it be a little more like this:


    No, not exactly.

    >
    > # in utilities module
    > shared_cursor = DatabaseAccess_instance #but how? see my question
    > below...


    How what?

    > # in importer
    > import utilities
    > self.shared_cursor = utilities.shared_cursor ("self" is here to make
    > cursor available to all functions in importer


    Umm no. For one you're using self incorrectly. For two, it already is
    visible to all functions in the module. You just have to refer to it as
    "utilities.shared_cursor."

    > My only problem, then, is I create the shared_cursor from within a
    > function within the instance of DatabaseAccess(). How then do I pass
    > it from within the function's namespace to the module's namespace so
    > that I can do that first line?


    Every function in a module has access to the module's global namespace.
    And your shared_cursor is there, inside of the utilities reference,
    since utilities was imported into your module, "importer."
     
    Michael Torrie, Feb 7, 2013
    #4
  5. On 02/06/2013 05:03 PM, Michael Torrie wrote:
    > Every function in a module has access to the module's global namespace.
    > And your shared_cursor is there, inside of the utilities reference,
    > since utilities was imported into your module, "importer."


    Just to be clear:

    mod1.py:
    a=5

    ------------------------
    mod2.py:
    import mod1

    def testfunc1():
    print mod1.a

    def testfunc2():
    mod1.a = 6

    -------------------------
    main.py:
    import mod1
    import mod2

    mod2.testfunc1()
    mod2.testfunc2()
    mod2.testfunc1()

    -----------------------

    The main.py program will print out "5" and "6."

    If I understand your original question, this example will demonstrate
    it. But I could have understood wrong!
     
    Michael Torrie, Feb 7, 2013
    #5
  6. CM

    c Guest

    On Feb 6, 7:03 pm, Michael Torrie <> wrote:
    > On 02/06/2013 03:41 PM, CM wrote:
    >
    > > Thank you.  But, I'm sorry, I'm not following this enough to get it to
    > > work.  Shouldn't it be a little more like this:

    >
    > No, not exactly.
    >
    >
    >
    > > # in utilities module
    > > shared_cursor =  DatabaseAccess_instance  #but how? see my question
    > > below...

    >
    > How what?
    >
    > > # in importer
    > > import utilities
    > > self.shared_cursor = utilities.shared_cursor  ("self" is here to make
    > > cursor available to all functions in importer

    >
    > Umm no.  For one you're using self incorrectly.  For two, it already is
    > visible to all functions in the module.  You just have to refer to it as
    > "utilities.shared_cursor."


    I was using self correctly, I think; but I should have said that the
    code in the importing module would be within a class, so self there
    refers to that class. But that's a side point.

    I agree that utilities.shared_cursor is visible within the importing
    module. But the problem below remains for me...

    > > My only problem, then, is I create the shared_cursor from within a
    > > function within the instance of DatabaseAccess().  How then do I pass
    > > it from within the function's namespace to the module's namespace so
    > > that I can do that first line?

    >
    > Every function in a module has access to the module's global namespace.
    >  And your shared_cursor is there, inside of the utilities reference,
    > since utilities was imported into your module, "importer."


    But the function in the module is also within a *class* so I don't
    think the function does have access to the module's global namespace.
    Here's the hierarchy:

    -- Module namespace....
    ---- class namespace (DatabaseAccess is the name of the class)
    ---- function namespace
    This is where the cursor is created. How do I get it
    into the module namespace?

    Che
     
    c, Feb 7, 2013
    #6
  7. CM

    CM Guest

    I was using self correctly, I think; but I should have said that the
    code in the importing module would be within a class, so self there
    refers to that class. But that's a side point.

    I agree that utilities.shared_cursor is visible within the importing
    module. But the problem below remains for me...

    > > My only problem, then, is I create the shared_cursor from within a
    > > function within the instance of DatabaseAccess(). How then do I pass
    > > it from within the function's namespace to the module's namespace so
    > > that I can do that first line?


    > Every function in a module has access to the module's global namespace.
    > And your shared_cursor is there, inside of the utilities reference,
    > since utilities was imported into your module, "importer."


    But the function in the module is also within a *class* so I don't
    think the function does have access to the module's global namespace.
    Here's the hierarchy:

    -- Module namespace....
    ---- class namespace (DatabaseAccess is the name of the class)
    ---- function namespace
    This is where the cursor is created. How do I get it
    into the module namespace?
     
    CM, Feb 7, 2013
    #7
  8. CM

    Ethan Furman Guest

    On 02/06/2013 04:43 PM, c wrote:
    > But the function in the module is also within a *class* so I don't
    > think the function does have access to the module's global namespace.
    > Here's the hierarchy:
    >
    > -- Module namespace....
    > ---- class namespace (DatabaseAccess is the name of the class)
    > ---- function namespace
    > This is where the cursor is created. How do I get it
    > into the module namespace?


    In the class namespace you have something like:

    self.shared_cursor = ...

    to get that into the module namespace instead, just remove the 'self':

    shared_cursor = ...

    --
    ~Ethan~
     
    Ethan Furman, Feb 7, 2013
    #8
  9. On 02/06/2013 05:45 PM, CM wrote:
    > But the function in the module is also within a *class* so I don't
    > think the function does have access to the module's global namespace.
    > Here's the hierarchy:
    >
    > -- Module namespace....
    > ---- class namespace (DatabaseAccess is the name of the class)
    > ---- function namespace
    > This is where the cursor is created. How do I get it
    > into the module namespace?


    Oh I see. You're trying to set a variable in the current module's
    global namespace. There's two ways to do this, the first one is cleaner
    and preferred:

    1. Have a function in DatabaseAccess return the cursor then then set it
    to a name in code that runs at the module level.

    2. use the "global" keyword in the method:

    def mymethod(self):
    global blah

    blah = something


    Then your module has has blah in it's global method now. If you want to
    stick a variable in another method's global namespace, as long as you've
    imported it you just go:

    module.newvariable = something
     
    Michael Torrie, Feb 7, 2013
    #9
  10. CM

    Ethan Furman Guest

    On 02/06/2013 04:57 PM, Ethan Furman wrote:
    > On 02/06/2013 04:43 PM, c wrote:
    >> But the function in the module is also within a *class* so I don't
    >> think the function does have access to the module's global namespace.
    >> Here's the hierarchy:
    >>
    >> -- Module namespace....
    >> ---- class namespace (DatabaseAccess is the name of the class)
    >> ---- function namespace
    >> This is where the cursor is created. How do I get it
    >> into the module namespace?

    >
    > In the class namespace you have something like:
    >
    > self.shared_cursor = ...
    >
    > to get that into the module namespace instead, just remove the 'self':
    >
    > shared_cursor = ...


    Correction:

    As Michael Torrie pointed out, the 'global' keyword is needed:

    global shared_cursor
    shared_cursor = ...
     
    Ethan Furman, Feb 7, 2013
    #10
  11. CM

    Rick Johnson Guest

    On Wednesday, February 6, 2013 7:36:28 PM UTC-6, Ethan Furman wrote:
    > As Michael Torrie pointed out, the 'global' keyword is needed:


    Wrong. The global keyword is in fact NOT needed and something i consider to be another wart of the language (PyWart on this subject coming soon!).

    Now, whilst Micheal's advice is valid python code, i would strongly suggest against encouraging people to use the global keyword when they could simply declare the variable beforehand. I know what you are thinking:

    """ But python does not /require/ us to declare global variables if we use the global keyword"""

    Yes, i know. But i just hate to have variables created "magically" in the middle of execution! ESPECIALLY if these variables are going to be accessed from another module(s). *sniff-sniff* does anyone smell what i smell?

    Listen. I want to know every variable and every CONSTANT that will exist in the module namespace, and i want to know these facts BEFORE i read anything else. So please declare them at the top of each module.


    Hierarchy of module code structure:

    0. shebang lines
    1. stdlib import statements
    2. 3rd party and dependency import statements
    3. CONSTANTS
    4. $globalVariables
    5. module functions
    6. module classes (bka: Object Definitions)
    7. Testing Area

    So if you want to use "global variables" , (bka: Module level variables), then simply declare them with a None value like this:

    globalVariable = None

    But don't pat yourself on the back just yet! Place a little comment so the reader will understand that this variable is accessed from ANOTHER namespace.

    sharedCursor = None # Set by "Class.blah"; Whored out to X,Y and Z!

    In this manner i will not be blindsided by proper use of poor language features.
     
    Rick Johnson, Feb 8, 2013
    #11
  12. CM

    Rick Johnson Guest

    On Wednesday, February 6, 2013 7:36:28 PM UTC-6, Ethan Furman wrote:
    > As Michael Torrie pointed out, the 'global' keyword is needed:


    Wrong. The global keyword is in fact NOT needed and something i consider to be another wart of the language (PyWart on this subject coming soon!).

    Now, whilst Micheal's advice is valid python code, i would strongly suggest against encouraging people to use the global keyword when they could simply declare the variable beforehand. I know what you are thinking:

    """ But python does not /require/ us to declare global variables if we use the global keyword"""

    Yes, i know. But i just hate to have variables created "magically" in the middle of execution! ESPECIALLY if these variables are going to be accessed from another module(s). *sniff-sniff* does anyone smell what i smell?

    Listen. I want to know every variable and every CONSTANT that will exist in the module namespace, and i want to know these facts BEFORE i read anything else. So please declare them at the top of each module.


    Hierarchy of module code structure:

    0. shebang lines
    1. stdlib import statements
    2. 3rd party and dependency import statements
    3. CONSTANTS
    4. $globalVariables
    5. module functions
    6. module classes (bka: Object Definitions)
    7. Testing Area

    So if you want to use "global variables" , (bka: Module level variables), then simply declare them with a None value like this:

    globalVariable = None

    But don't pat yourself on the back just yet! Place a little comment so the reader will understand that this variable is accessed from ANOTHER namespace.

    sharedCursor = None # Set by "Class.blah"; Whored out to X,Y and Z!

    In this manner i will not be blindsided by proper use of poor language features.
     
    Rick Johnson, Feb 8, 2013
    #12
  13. On 02/07/2013 07:14 PM, Rick Johnson wrote:
    > On Wednesday, February 6, 2013 7:36:28 PM UTC-6, Ethan Furman wrote:
    >> As Michael Torrie pointed out, the 'global' keyword is needed:

    >
    > Wrong. The global keyword is in fact NOT needed and something i
    > consider to be another wart of the language (PyWart on this subject
    > coming soon!).


    Actually in both Python 2 and 3, the global keyword is, in fact needed.
    Otherwise the name binding in the function hides the global name. So
    no matter if you declare the variable in the module itself (which yes I
    agree you should always do!), you need the global keyword in the
    function if you want to overwrite the name in the module's global namespace.

    Observe the following code which I tested on both python2 and python3:
    --------
    from __future__ import print_function

    my_global_var = 4

    def test_func():
    #global my_global_var
    my_global_var = 6

    if __name__ == "__main__":
    print(my_global_var)
    test_func()
    print(my_global_var)

    ---------

    Without the global statement, you get 4 printed out both times. At
    least on the python interpreters I have handy. With the global
    statement uncommented, I get 4 and 6.

    Do you understand the difference between binding a name to an object and
    variable assignment? Because that's the reason we see this behavior.
    This would be a gotcha in this case. Not a wart, but simply something
    to be aware of.
     
    Michael Torrie, Feb 8, 2013
    #13
  14. On 02/07/2013 07:14 PM, Rick Johnson wrote:

    > So if you want to use "global variables" , (bka: Module level
    > variables), then simply declare them with a None value like this:
    >
    > globalVariable = None


    This is a nice convention, but at best it's just a helpful notation that
    helps a programmer know something useful may likely be bound to this
    name in the future.

    The '=' sign in Python isn't an assignment operator, at least in this
    case; it's a binding operator. Thus any future line that sets
    globalVariable to something isn't assigning a value to this
    already-declared variable. Instead it's binding the name globalValue to
    a new object, and overwriting the name in the module dictionary. That's
    of course why the global keyword is required, so that Python will use
    the module dictionary instead of the local scope one.
     
    Michael Torrie, Feb 9, 2013
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Guadala Harry

    Share SQL DB Among Dozens of Sites

    Guadala Harry, Feb 21, 2004, in forum: ASP .Net
    Replies:
    1
    Views:
    332
    Peter Bromberg [C# MVP]
    Feb 21, 2004
  2. MK
    Replies:
    6
    Views:
    717
    noSpAm0000
    May 16, 2005
  3. red floyd
    Replies:
    1
    Views:
    501
    Zhang Yan
    Sep 6, 2003
  4. just_life
    Replies:
    0
    Views:
    708
    just_life
    Aug 1, 2007
  5. Saraswati lakki
    Replies:
    0
    Views:
    1,408
    Saraswati lakki
    Jan 6, 2012
Loading...

Share This Page