FAQ
Hi,

I've been having trouble understanding the difference between global
namespace within and between modules. For example, I can program a
subthread to see a global name (a threaded event to be specific);
however, somehow when I break up my code into different modules, the
subthread can no longer see the global name in the main program.

Here's an example of what I'm trying to accomplish:

Working script pseudo-code:
======================================================
# main.py
---------------------------
import std modules

def thread1
def thread2

launch thread1: wait for event
launch thread2: signal thread1's event
======================================================
#END: Broken script pseudo-code

and here's it's seemingly equivalent part...

#START: Broken script pseudo-code
======================================================
# subfile.py:
---------------------------
import std modules

def thread1
def thread2

---------------------------
# main.py
import std modules
from subfile import thread1, thread2 # this should be the only
difference

launch thread1: wait for event
launch thread2: signal thread1's event
======================================================
#END: Broken script pseudo-code

The broken code would yield the following exception when thread2 tries
to signal thread1's event:
"NameError: global name 'myName' is not defined"

I hope I didn't simplify the problem too much, but I didn't want to
paste 200 lines of code for no one to read.

Obviously I'm missing something regarding namespace and global scopes.
Would anyone be able to point out what I've overlooked? Any help is
appreciated.

-Jason

Search Discussions

  • Peter Otten at Nov 24, 2004 at 8:10 am

    Jason wrote:

    I've been having trouble understanding the difference between global
    namespace within and between modules. For example, I can program a
    Did you know that global variables are only global to the module?
    from subfile import thread1, thread2 # this should be the only
    This will bind the names thread1 and thread2 in the importing module, i. e.
    you have now two distinct thread1 variables no longer pointing to the same
    object after a thread1 = something assignment in one of the modules. Do

    import subfile

    instead and access the variables with qualified names

    subfile.thread1 = something

    in all modules except subfile.py, and everything should be OK.

    Peter
  • Jason at Nov 24, 2004 at 9:55 pm
    Thanks for your quick reply, Peter.

    I had to dust off my Learning Python book, which I had read cover to
    cover many months ago. After re-reading some key sections I now
    understand what 'global' scope really means and why you suggested
    importing the module directly, rather than copying the namespace with
    the 'from' statement.

    When importing the module directly as 'import module' in lieu of 'from
    module import *', this doesn't seem to address the issue I'm having.

    My main program now imports the submodule names that must be qualified
    with the module name, but the function in one submodule still can't
    see the function (class instance method to be exact) defined in the
    other submodule.

    I suppose I can post the test code I was using. The multithreaded
    hierarchy mimics that of my 'real' program that I need to integrate my
    code into, so don't let this complexity confuse you.

    ===========================================================
    # main.py
    #
    #!/usr/bin/env python
    #
    # A customized class to terminate a thread using the threading
    module's event-
    # based functionality.
    #
    ###############################################################################

    import threading, time

    from hb_imports import *
    import hb_imports
    import hb_global

    def main():
    # launch WatchDog timer thread
    bcast_watchdog = hb_global.WatchDog(timeout=3)
    bcast_watchdog.setDaemon(1)
    bcast_watchdog.start()

    # launch global arbiter
    glob_arbiter = threading.Thread(target=hb_global.global_arbiter)
    glob_arbiter.setDaemon(1)
    glob_arbiter.start()

    time.sleep(7)
    cfg['ISROOT'] = False # simulation: no longer root again

    time.sleep(7)

    if __name__ == '__main__':
    main()

    ===========================================================
    # hb_global.py

    import threading, time
    import hb_stethoscope
    from hb_imports import *

    class WatchDog(threading.Thread):
    def __init__(self, name='WatchDog', timeout=1.0):
    self._timerevent = threading.Event() # assign event to instance
    self._waitperiod = timeout # assign timeout delay to instance
    variable

    threading.Thread.__init__(self, name=name)

    def run(self):
    while 1:
    while not cfg['ISROOT']:
    print now() + 'Timer started. %s seconds to receive ping.' %
    self._waitperiod

    # initialize timer and flags
    self._timerevent.clear() # BE KIND. REWIND.
    self._intervened = False # init flag denoting intervention
    occurred

    # wait for reset() method to be called or timeout
    self._timerevent.wait(self._waitperiod)

    # if _intervened flag not set AND still not a root server (status
    could change in countdown)
    if not self._intervened and not cfg['ISROOT']:
    print now() + "No broadcasts received in %s seconds! Becoming a
    root server." % (self._waitperiod,)
    cfg['ISROOT'] = True # modify root status

    time.sleep(0.1) # sleep 100ms to avoid constant polling

    def reset(self):
    self._intervened = True
    self._timerevent.set()


    def global_arbiter():
    threading.Thread(target=hb_stethoscope.stethoscope).start()

    ===========================================================
    # hb_stethoscope.py

    import threading, time
    import hb_global
    from hb_imports import *

    def stethoscope():
    for i in range(6):
    if i == 3:
    time.sleep(4)
    sim_delay = 1
    time.sleep(sim_delay)
    threading.Thread(target=bcast_handle).start()

    def bcast_handle():
    print now() + 'Receiving broadcast ping. Reseting watchdog timer.'
    hb_global.bcast_watchdog.reset()

    ===========================================================
    # hb_imports.py

    import time

    otime = time.time()

    def now():
    ctime = time.time()
    return '%.2f :: ' % (ctime-otime,)

    cfg = dict()
    cfg['ISROOT'] = False

    ===========================================================

    The last line in hb_stethoscope.py, hb_global.bcast_watchdog.reset(),
    is _supposed_ to call the WatchDog.reset() class instance method in
    hb_global.py.

    I've been very frustrated trying to find out why I can't access this
    method.

    Thanks for anyone taking a look at this problem.

    Happy Thanksgiving,

    Jason
  • Peter Otten at Nov 25, 2004 at 8:14 am

    Jason wrote:

    def main():
    # launch WatchDog timer thread
    bcast_watchdog = hb_global.WatchDog(timeout=3) [...]
    The last line in hb_stethoscope.py, hb_global.bcast_watchdog.reset(),
    is _supposed_ to call the WatchDog.reset() class instance method in
    hb_global.py.
    It seems you are creating bcast_watchdog as a local variable in
    __main__.main(). How would you suppose it to become magically inserted in
    the hb_global namespace? Do

    def main():
    bcast_watchdog = hb_global.WatchDog(timeout=3)
    hb_global.bcast_watchdog = bcast_watchdog

    to insert the WatchDog instance into the hb_global module. (Note that there
    may be other problems as I didn't look any further)

    Peter

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedNov 24, '04 at 5:58a
activeNov 25, '04 at 8:14a
posts4
users2
websitepython.org

2 users in discussion

Peter Otten: 2 posts Jason: 2 posts

People

Translate

site design / logo © 2022 Grokbase