namespace & imported modules

J

Jason

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
 
P

Peter Otten

Jason said:
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
 
J

Jason

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
 
P

Peter Otten

Jason said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,533
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top