Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #38253 > unrolled thread

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

Started byCM <cmpython@gmail.com>
First post2013-02-05 20:40 -0800
Last post2013-02-06 18:08 -0700
Articles 14 — 6 participants

Back to article view | Back to comp.lang.python


Contents

  best way to share an instance of a class among modules? CM <cmpython@gmail.com> - 2013-02-05 20:40 -0800
    Re: best way to share an instance of a class among modules? Terry Reedy <tjreedy@udel.edu> - 2013-02-06 00:04 -0500
      Re: best way to share an instance of a class among modules? CM <cmpython@gmail.com> - 2013-02-06 14:41 -0800
        Re: best way to share an instance of a class among modules? Michael Torrie <torriem@gmail.com> - 2013-02-06 17:03 -0700
          Re: best way to share an instance of a class among modules? c <chaelon@gmail.com> - 2013-02-06 16:43 -0800
            Re: best way to share an instance of a class among modules? Ethan Furman <ethan@stoneleaf.us> - 2013-02-06 16:57 -0800
            Re: best way to share an instance of a class among modules? Ethan Furman <ethan@stoneleaf.us> - 2013-02-06 17:36 -0800
              Re: best way to share an instance of a class among modules? Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-07 18:14 -0800
                Re: best way to share an instance of a class among modules? Michael Torrie <torriem@gmail.com> - 2013-02-07 23:05 -0700
                Re: best way to share an instance of a class among modules? Michael Torrie <torriem@gmail.com> - 2013-02-08 21:54 -0700
              Re: best way to share an instance of a class among modules? Rick Johnson <rantingrickjohnson@gmail.com> - 2013-02-07 18:14 -0800
        Re: best way to share an instance of a class among modules? Michael Torrie <torriem@gmail.com> - 2013-02-06 17:14 -0700
          Re: best way to share an instance of a class among modules? CM <cmpython@gmail.com> - 2013-02-06 16:45 -0800
            Re: best way to share an instance of a class among modules? Michael Torrie <torriem@gmail.com> - 2013-02-06 18:08 -0700

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

FromCM <cmpython@gmail.com>
Date2013-02-05 20:40 -0800
Subjectbest way to share an instance of a class among modules?
Message-ID<15fe7153-a77a-49eb-9cf8-d4e59b4a2079@z9g2000vbx.googlegroups.com>
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

[toc] | [next] | [standalone]


#38254

FromTerry Reedy <tjreedy@udel.edu>
Date2013-02-06 00:04 -0500
Message-ID<mailman.1401.1360127082.2939.python-list@python.org>
In reply to#38253
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

[toc] | [prev] | [next] | [standalone]


#38310

FromCM <cmpython@gmail.com>
Date2013-02-06 14:41 -0800
Message-ID<5db4add7-ab9c-4311-b3b6-24156cd6f248@z4g2000vbz.googlegroups.com>
In reply to#38254
On Feb 6, 12:04 am, Terry Reedy <tjre...@udel.edu> 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?

[toc] | [prev] | [next] | [standalone]


#38318

FromMichael Torrie <torriem@gmail.com>
Date2013-02-06 17:03 -0700
Message-ID<mailman.1432.1360195406.2939.python-list@python.org>
In reply to#38310
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."

[toc] | [prev] | [next] | [standalone]


#38320

Fromc <chaelon@gmail.com>
Date2013-02-06 16:43 -0800
Message-ID<aa4c4a88-5d14-4875-aa1c-0e611cc0badd@z4g2000vbz.googlegroups.com>
In reply to#38318
On Feb 6, 7:03 pm, Michael Torrie <torr...@gmail.com> 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

[toc] | [prev] | [next] | [standalone]


#38323

FromEthan Furman <ethan@stoneleaf.us>
Date2013-02-06 16:57 -0800
Message-ID<mailman.1435.1360199783.2939.python-list@python.org>
In reply to#38320
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~

[toc] | [prev] | [next] | [standalone]


#38324

FromEthan Furman <ethan@stoneleaf.us>
Date2013-02-06 17:36 -0800
Message-ID<mailman.1436.1360202172.2939.python-list@python.org>
In reply to#38320
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 = ...

[toc] | [prev] | [next] | [standalone]


#38395

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-02-07 18:14 -0800
Message-ID<5b81481d-b7ee-40a2-92ba-4bfb174e1694@googlegroups.com>
In reply to#38324
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.

[toc] | [prev] | [next] | [standalone]


#38411

FromMichael Torrie <torriem@gmail.com>
Date2013-02-07 23:05 -0700
Message-ID<mailman.1479.1360303575.2939.python-list@python.org>
In reply to#38395
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.

[toc] | [prev] | [next] | [standalone]


#38497

FromMichael Torrie <torriem@gmail.com>
Date2013-02-08 21:54 -0700
Message-ID<mailman.1532.1360385670.2939.python-list@python.org>
In reply to#38395
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.

[toc] | [prev] | [next] | [standalone]


#38396

FromRick Johnson <rantingrickjohnson@gmail.com>
Date2013-02-07 18:14 -0800
Message-ID<mailman.1469.1360289657.2939.python-list@python.org>
In reply to#38324
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.

[toc] | [prev] | [next] | [standalone]


#38319

FromMichael Torrie <torriem@gmail.com>
Date2013-02-06 17:14 -0700
Message-ID<mailman.1433.1360196074.2939.python-list@python.org>
In reply to#38310
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!


[toc] | [prev] | [next] | [standalone]


#38321

FromCM <cmpython@gmail.com>
Date2013-02-06 16:45 -0800
Message-ID<ef7640df-034a-4c20-a58a-53117c6f4a56@cd3g2000vbb.googlegroups.com>
In reply to#38319
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?

[toc] | [prev] | [next] | [standalone]


#38322

FromMichael Torrie <torriem@gmail.com>
Date2013-02-06 18:08 -0700
Message-ID<mailman.1434.1360199338.2939.python-list@python.org>
In reply to#38321
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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web