I'm trying to import a module, while passing some global variables, but it does not seem to work:
File test_1:
test_2 = __import__("test_2", {"testvar": 1})
File test_2:
print testvar
This seems like it should work, and print a 1, but I get the following error when I run test_1:
Traceback (most recent call last):
File ".../test_1.py", line 1, in <module>
print testvar
NameError: name 'testvar' is not defined
What am I doing wrong?
EDIT:
As I commented later on, this is an attempt to replace the functions within a graphics library. Here is a sample program (that my teacher wrote) using that library:
from graphics import *
makeGraphicsWindow(800, 600)
############################################################
# this function is called once to initialize your new world
def startWorld(world):
world.ballX = 50
world.ballY = 300
return world
############################################################
# this function is called every frame to update your world
def updateWorld(world):
world.ballX = world.ballX + 3
return world
############################################################
# this function is called every frame to draw your world
def drawWorld(world):
fillCircle(world.ballX, world.ballY, 50, "red")
############################################################
runGraphics(startWorld, updateWorld, drawWorld)
Note that this code is designed such that people who have never (or almost never) seen ANY code before (not just python) would be able to understand with little effort.
Example for rewriting the function:
Original code:
def drawPoint(x, y, color=GLI.foreground):
GLI.screen.set_at((int(x),int(y)), lookupColor(color))
Injected code:
# Where self is a window (class I created) instance.
def drawPoint(x, y, color = self.foreground):
self.surface.set_at((int(x), int(y)), lookupColor(color))
I guess my real question is: how would I inject global functions/variables into an imported module before the module runs...?
As the docs explain, the globals
parameter to __import__
does not "inject" extra globals into the imported module, as you appear to believe -- indeed, what's normally passed there is the globals()
of the importing module, so such injection would be highly problematic if it happened. Indeed, __import__
's docs specifically say:
The standard implementation does not use its locals argument at all, and uses its globals only to determine the package context of the import statement.
Edit: if you do need injection, e.g. into an empty imported module, as the OP suggested in a comment, that's easy as long as you're OK with doing it right after the import:
themod = __import__(themodname)
themod.__dict__.update(thedict)
The imported module's body will not be aware of still-to-happen injections, but that's clearly no matter if said body is empty anyway;-). Right after the import, you can inject to your heart's contents, and all following uses of that module will see your injections as if they were bona fide module-level bound names (because they are;-).
You could even, if you wished, save the need for an empty .py
module to start with...:
import new, sys
themod = new.module(themodname)
sys.modules[themodname] = themod
themod.__dict__.update(thedict)
Edit: the OP tries to clarify in an edit of the Q...:
I guess my real question is: how would I inject global functions/variables into an imported module before the module runs...?
"The module runs" doesn't make much sense -- modules are loaded (which executes their body), just once (unless re-loaded explicitly later)... they never "run" per se. Given an empty module, you first import it (which executes nothing since the module's empty), then you can if you wish use a mix of themodule.__dict__.update
and attribute assignment to populate the module -- functions are not automatically called when just mentioned (as the OP expresses fears they will be in a comment), so they can be treated just like any other variable in this respect (and most others, which is why Python's said to have first class functions).
I was facing the same problem... And I convinced myself with following technique... I donno whtr this will be usefull for you or not!
File2: test1.py
global myvar
myvar = "some initial value"
print myvar
test = __import__("test2")
print myvar
File2: test2.py
import inspect
stk = inspect.stack()[1]
myvar = inspect.getmodule(frm[0]).myvar
print myvar
myvar = "i am changing its value."
Here variable is passed from module1 to module2 and that too it is passed by reference.
As said, the __import__
function doesn't add globals to a new module. If you want to do that, I'd suggest adding some kind of initialize() function that assigns a value to a pre-declared global table, like this:
gTable = {}
gInited = False
def initialize(table):
if(not gInited):
gTable = table
gInited = True
def getGlobal(name):
if(name in gTable):
return gTable[name]
else:
throw NameError("name '"+name+"' is not defined")
def setGlobal(name, value):
gTable[name] = value
def mod_main():
print getGlobal("testvar")
and import it like this:
import modGlobalsTest
modGlobalsTest.initialize({"testvar": 1})
modGlobalsTest.mod_main()
If you want to change the functions in the imported library, you can do something like this:
import foobar
def bar(x):
return x+1
foobar.foo = bar
to replace foobar.foo with the custom function bar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With