Module scope is functionally almost-global. That is, it's so close to global you'll want to use it, but it's far enough away that you'll end up shooting yourself in the foot.
Consider this code snippet:
#!/bin/env python2.6
import os
import sys
varname = 33
vardict = { 'a' : 44 }
# other imports here
print "Starting!"
def something():
print "thing", varname
print "next"
something()
print "end"
This is what I call drop-thru code. All the variables are global, and the call to something() will fail because varname is out of scope.
Contrast this with what I prefer, well-encapsulated code:
#!/bin/env python2.6
import os
import sys
class SomeThing(object):
def __init__(self):
self.varname = 33
def something(self):
print "thing", self.varname
def main(self):
self.vardict = { 'a' : 44 }
# other imports here
print "Starting!"
print "next"
self.something()
print "end"
st = SomeThing()
st.main()
Nothing is global, it's obvious what the scope for things is. Clean, beautiful, easy to understand.
There are lots of examples of scope problems. I created this one for my team so they understood my frustration:
outside = 1
def function1():
try:
print "f1 outside: %s" % (outside)
outside += 1
except:
print "no outside in function1."
print "a outside: %s" % (outside)
function1()
print "b outside: %s" % (outside)
def function2():
global outside
try:
print "f2 outside: %s" % (outside)
outside += 1
except:
print "no outside in function2"
function2()
function2()
class Dum(object):
def __init__(self):
print "dum instantiated."
def main(self):
print "Dum main outside: %s" % (outside)
def changeOutside(self, inval):
outside = inval
print "Dum changed: outside: %s" % (outside)
def changeGlobalOutside(self, inval):
global outside
outside = inval
print "Dum changed: outside: %s" % (outside)
d = Dum()
print "c outside: %s" % (outside)
d.main()
print "d outside: %s" % (outside)
d.changeOutside(33)
print "e outside: %s" % (outside)
d.main()
d.changeGlobalOutside(44)
d.main()
print "f outside: %s" % (outside)
______________________________________________________
output:
krice4@zaphod:~/checkouts/userSandboxes/krice4$ python scopeTest.py
a outside: 1
no outside in function1.
b outside: 1
f2 outside: 1
f2 outside: 2
dum instantiated.
c outside: 3
Dum main outside: 3
d outside: 3
Dum changed: outside: 33
e outside: 3
Dum main outside: 3
Dum changed: outside: 44
Dum main outside: 44
f outside: 44
In short, Drop-Thru Code is considered harmful. It allows for lots of scope problems that show up as bugs and frustrations later. So, avoid them. Put all the vars you can in a class and invoke that class, you'll be glad you did. IMHO.